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