DataTrigger внутри ItemTemplate-DataTemplate не срабатывает при изменении свойства

Я довольно новичок в WPF и сейчас пытаюсь понять, как добавить стилизованные шаблоны данных в элемент управления, в данном случае ListBox.

Я пытаюсь сделать браузер элементов с ListBox и выделить ListBoxItem с пользовательским цветом, когда он щелкает, используя цветной прямоугольник на заднем плане.

ListBox связан с коллекцией ObservableCollection с несколькими свойствами, включая свойство IsOpened.

<ListBox x:Name="MainPage_Entries" Height="643" Canvas.Left="10" Canvas.Top="10" Width="230">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="White" BorderThickness="1">
                <WrapPanel Margin="-2,0,0,0" HorizontalAlignment="Stretch">
                    <Grid HorizontalAlignment="Stretch">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="30"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Rectangle Margin="0" HorizontalAlignment="Stretch" Height="40" Grid.ColumnSpan="2">
                            <Rectangle.Style>
                                <Style TargetType="Rectangle">
                                    <Setter Property="Fill" Value="Gray"/>
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding IsOpened}" Value="True">
                                            <Setter Property="Fill" Value="Black"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Rectangle.Style>
                        </Rectangle>

                        <Image Source="{Binding SourceImage}" Height="30"/>
                        <TextBlock Margin="3,1,3,0" Text="{Binding SetName}" Grid.Column="1" VerticalAlignment="Top" Width="188" FontFamily="Arial" FontSize="16" Foreground="White"/>
                        <TextBlock Margin="3,0,3,5" Text="{Binding OutputName}" Grid.Column="1" VerticalAlignment="Bottom" Width="188" Foreground="White" FontSize="10" FontStyle="Italic"/>
                    </Grid>
                </WrapPanel>
            </Border>


        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBoxItem_ClickDown"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

При щелчке по элементу ListBoxItem свойство IsOpened выбранного элемента устанавливается в значение "Ложь", а для выбранного элемента значение "Истина". Даже если изменение свойства выполняется в ObservableCollection, триггер остается нетронутым, а фон остается черным (инициализированное значение IsOpened равно True).

РЕДАКТИРОВАТЬ:

DataTrigger до сих пор изменился:

<DataTrigger Binding="{Binding Path=IsOpened, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}}" Value="True">
    <Setter Property="Fill" Value="Black"/>
</DataTrigger>

И текущее состояние класса записи:

public class EntryItem : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public string SetName { get; set; }

    public string SourceImage { get; set; }

    public EntryItem(string name)
    {
        SetName = name;
        IsOpened = true;
    }

    private bool _isOpened;
    public bool IsOpened
    {
        get { return _isOpened; }
        set {
            _isOpened = value;
            NotifyPropertyChanged();
        }
    }
}

Добавляя их, фон всех записей остается серым, даже если один "IsOpened".

РЕДАКТИРОВАТЬ 2:

Удаление бита RelativeSource заставило его работать.
Вывод: реализовать INotifyPropertyChanged.

2 ответа

Решение

Класс где IsOpened это свойство должно реализовывать интерфейс INotifyPropertyChanged и поднимать PropertyChanged событие, когда IsOpened свойство установлено:

class DataObject : INotifyPropertyChanged
{
    private bool _isOpened;
    public bool IsOpened
    {
        get { return _isOpened; }
        set { _isOpened = value; NotifyPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Если вы уверены, что этот список имеет тот же DataContext, что и свойство IsOpened, существует, я постараюсь разрешить его, настроив RelativeSource для самого списка:

<Rectangle Margin="0" HorizontalAlignment="Stretch" Height="40" Grid.ColumnSpan="2">
    <Rectangle.Style>
        <Style TargetType="Rectangle">
            <Setter Property="Fill" Value="Gray"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsOpened, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}}" Value="True">
                    <Setter Property="Fill" Value="Black"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Rectangle.Style>
</Rectangle>
Другие вопросы по тегам