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>