ItemTemplate-DataTemplate 内的 DataTrigger 未在 属性 更改时触发
DataTrigger inside ItemTemplate-DataTemplate not triggering upon property change
我是 WPF 的新手,目前我正在尝试弄清楚如何将程式化的 DataTemplates 添加到控件,在本例中是一个 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 属性 被设置为 False,被点击的项目被设置为 True。
即使在 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>
以及条目class的当前状态:
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。
如果您确定此列表框具有与 IsOpened 属性 相同的 DataContext,我会尝试通过将 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>
定义IsOpened
属性的class应该实现INotifyPropertyChanged接口,并在IsOpened
时引发PropertyChanged
事件] 属性 已设置:
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));
}
}
我是 WPF 的新手,目前我正在尝试弄清楚如何将程式化的 DataTemplates 添加到控件,在本例中是一个 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 属性 被设置为 False,被点击的项目被设置为 True。 即使在 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>
以及条目class的当前状态:
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。
如果您确定此列表框具有与 IsOpened 属性 相同的 DataContext,我会尝试通过将 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>
定义IsOpened
属性的class应该实现INotifyPropertyChanged接口,并在IsOpened
时引发PropertyChanged
事件] 属性 已设置:
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));
}
}