属性更改时不会触发ItemTemplate-DataTemplate中的DataTrigger

时间:2018-10-05 14:02:09

标签: c# wpf xaml observablecollection datatrigger

我对WPF还是很陌生,我目前正在尝试弄清楚如何将样式化的DataTemplates添加到控件(在这种情况下为ListBox)中。

我正在尝试使用ListBox创建一个项目浏览器,并在背景中使用彩色矩形单击该框时用自定义颜色突出显示ListBoxItem。

ListBox通过多个属性(包括IsOpened属性)链接到ObservableCollection。

joinBy: 'name',

在单击ListBoxItem时,所选项目的IsOpened属性将设置为False,将单击的属性设置为True。 即使ObservableCollection中的属性更改成功,触发器仍保持不变,背景仍然为黑色(IsOpened的初始化值为True)。

编辑:

到目前为止,DataTrigger已更改为:

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

该条目的类的当前状态:

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

通过添加这些内容,即使一个“ IsOpened”,所有条目的背景也保持灰色。

编辑2:

删除RelativeSource位使其起作用。
结论:实施INotifyPropertyChanged。

2 个答案:

答案 0 :(得分:0)

如果您确定此列表框具有与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>

答案 1 :(得分:0)

定义了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));
    }
}