У меня есть родительский DataTemplate
с двумя дочерними DataTemplate
и хочу изменить свойство только одного из подкомпонентов дочернего шаблона (например, Label.Foreground
, TextBox.Background
и т.д.) На основе триггера. Я столкнулся с этим сообщением, которое предполагает привязку RelativeSource
, но после многих попыток я не могу заставить его работать, и я не уверен, как влиять только на один из дочерних шаблонов. Ниже показан мой ожидаемый конечный результат (любые/все правильные дочерние свойства необходимо изменить, чтобы показать, что они отличаются от левого ребенка).
Родительский DataTemplate
xaml:
<DataTemplate x:Key="CoupleDataTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<ContentControl Content="{Binding Left}"
ContentTemplate="{StaticResource PersonDataTemplate}"
/>
<Separator Grid.Column="1"
Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}"/>
<ContentControl Content="{Binding Right}"
ContentTemplate="{StaticResource PersonDataTemplate}"
Grid.Column="2"
/>
<!-- Does not work, but shows what I'm trying to do. -->
<!--<ContentControl.Style>
<Style TargetType="{StaticResource PersonDataTemplate}">
<Style.Triggers>
<DataTrigger Binding="{Binding
RelativeSource={RelativeSource FindAncestor,
AncestorType=ListBox},
Path=DataContext.IsFirstDifferent}"
Value="True">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>-->
</ContentControl>
</Grid>
</DataTemplate>
CoupleDataTemplate
затем используется в ListBox:
<ListBox ItemsSource="{Binding Couples}"
ItemTemplate="{StaticResource CoupleDataTemplate}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Свойство " Couples
public ObservableCollection<Couple> Couples { get; private set; }
Я пробовал всевозможные триггерные привязки безрезультатно. Является ли то, что я пытаюсь сделать, даже возможно? Если да, то что мне не хватает?
<DataTemplate x:Key="PersonDataTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right"
Name="FirstLabel"
Content="First:"
/>
<TextBox Grid.Row="0" Grid.Column="1"
HorizontalAlignment="Stretch"
Name="FirstTextBox"
Text="{Binding First}"
/>
<Label Grid.Row="1" Grid.Column="0"
HorizontalAlignment="Right"
Name="LastLabel"
Content="Last:"
/>
<TextBox Grid.Row="1" Grid.Column="1"
HorizontalAlignment="Stretch"
Name="LastTextBox"
Text="{Binding Last}"
/>
<Label Grid.Row="2" Grid.Column="0"
HorizontalAlignment="Right"
Name="SexLabel"
Content="Sex:"
/>
<ComboBox Grid.Row="2" Grid.Column="1"
HorizontalAlignment="Stretch"
Name="Sex"
ItemsSource="{Binding SexTypes, Mode=OneWay}"
SelectedItem="{Binding Sex}"
/>
</Grid>
</DataTemplate>
Ну, кто-то дал ответ, но почему-то удалил его. Это дало мне идею привязки к свойству Foreground
. Они предложили использовать свойство ContentControl.Tag
в CoupleDataTemplate
, но на самом деле это не работало более чем для одного свойства подкомпонента.
Решение, полученное из удаленного ответа, состояло в том, чтобы использовать относительное связывание с свойством DataContext.IsFirstDifferent
и использовать IValueConverter для преобразования bool
в цвет. Таким образом, для каждого Label
в PersonDataTemplate
я создаю пользовательскую относительную привязку. Например:
<Label Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right"
Name="FirstLabel"
Content="First:"
Foreground="{Binding Path=DataContext.IsFirstDifferent,
RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType={x:Type ContentControl}},
Converter={StaticResource IsDifferentConverter}}"
/>
Где источник IsDifferentConverter
:
public class DifferenceConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
return ((Boolean)value) ? "Red" : "Black";
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}