1

I have a parent DataTemplate with two child DataTemplate and want to change the property of just one of the child template's subcomponent (e.g. Label.Foreground, TextBox.Background, etc) based on a trigger. I came across this post which suggests a RelativeSource binding, but after many attempts I cannot get it to work and I'm not sure how to affect only one of the child templates. Below shows my expected end result (any/all of the right child properties need to be changed to show they're different from the left child).

enter image description here

The parent 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>

The CoupleDataTemplate is then used in a ListBox:

<ListBox ItemsSource="{Binding Couples}"
         ItemTemplate="{StaticResource CoupleDataTemplate}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

The Couples property is

public ObservableCollection<Couple> Couples { get; private set; }

I've tried all sorts of different trigger binding to no avail. Is what I'm trying to do even possible? If so, what am I missing?

The PersonDataTemplate per request

<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>
Community
  • 1
  • 1
E-rich
  • 9,243
  • 11
  • 48
  • 79
  • Add source of PersonDataTemplate, and of which type is {Binding Couples}? If it's IList, it doesn't make sense to bind against DataContext.IsFirstDifferent. – Erti-Chris Eelmaa Jun 24 '14 at 12:44

1 Answers1

0

Well, someone had given an answer but removed it for some reason. It gave me the idea of binding to the Foreground property. They had suggested using the ContentControl.Tag property in the CoupleDataTemplate, but that didn't really work for more than one subcomponent property.

The solution that evolved from the removed answer was to use a relative binding to the DataContext.IsFirstDifferent property and use a IValueConverter to convert the bool to a color. So, for each Label in the PersonDataTemplate I create a custom relative binding. For example:

<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}}"
       />

Where the IsDifferentConverter source is:

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;
    }

}
E-rich
  • 9,243
  • 11
  • 48
  • 79