Изменить стиль DataTemplate на лету через привязку

1

У меня есть родительский DataTemplate с двумя дочерними DataTemplate и хочу изменить свойство только одного из подкомпонентов дочернего шаблона (например, Label.Foreground, TextBox.Background и т.д.) На основе триггера. Я столкнулся с этим сообщением, которое предполагает привязку RelativeSource, но после многих попыток я не могу заставить его работать, и я не уверен, как влиять только на один из дочерних шаблонов. Ниже показан мой ожидаемый конечный результат (любые/все правильные дочерние свойства необходимо изменить, чтобы показать, что они отличаются от левого ребенка).

Изображение 174551

Родительский 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; }

Я пробовал всевозможные триггерные привязки безрезультатно. Является ли то, что я пытаюсь сделать, даже возможно? Если да, то что мне не хватает?

PersonDataTemplate за запрос

<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>
  • 0
    Добавить источник PersonDataTemplate, и какого типа {Binding Couples}? Если это IList <CoupleViewModel>, нет смысла связываться с DataContext.IsFirstDifferent.
Теги:
wpf
binding
datatemplate

1 ответ

0

Ну, кто-то дал ответ, но почему-то удалил его. Это дало мне идею привязки к свойству 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;
    }

}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню