WPF 数据与 ItemsControl 和 DataTrigger 的绑定

WPF data binding with ItemsControl and DataTrigger

我有一个 Foos 列表,每个都有 Name、ImageUrl 和 IsSelected 属性。图像显示在按钮内,IsSelected 为 true 的图像周围有红色边框。将其他人悬停在其周围也会显示红色边框。一切正常。

但是当我单击另一个项目时,它会将那个项目的 IsSelected 值更改为 true(而旧项目则为 false)。

ViewModel 然后说 NotifyOfPropertyChange(() => Foos);

但是边框没有任何变化。我试图按照这个例子 无济于事。如果您能发现错误,下面是我的 xaml 代码。

<ItemsControl ItemsSource="{Binding Foos}" Grid.Column="0">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Tag="{Binding FooName}" Click="SelectFoo" Cursor="Hand">
                <Image Height="100" Width="100" Source="{Binding ImageUrl}"/>

                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <Border BorderThickness="1" CornerRadius="3">
                            <ContentPresenter 
                                Margin="1"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                RecognizesAccessKey="True"/>

                            <Border.Style>
                                <Style TargetType="Border">
                                    <Setter Property="Background" Value="#292929"/>
                                    <Style.Triggers>
                                        <Trigger Property="IsMouseOver" Value="True">
                                            <Setter Property="BorderBrush" Value="Firebrick"/>
                                        </Trigger>
                                        <DataTrigger Binding="{Binding IsSelected}" Value="True">
                                            <Setter Property="BorderBrush" Value="Firebrick" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Border.Style>
                        </Border>
                    </ControlTemplate>
                </Button.Template>
            </Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

我认为您的 class Foo 应该实现 INotifyPropertyChanged 并在 IsSelected 属性 更改时调用事件 ProprtyChanged。 例如:

public class Foo : INotifyPropertyChanged
{
    private string _fooName;
    private bool _isSelected;

    protected void OnNotifyPropertyChanged(string property)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public string FooName { get => _fooName; set { _fooName = value; OnNotifyPropertyChanged(nameof(FooName)); } }
    public bool IsSelected { get => _isSelected; set { _isSelected = value; OnNotifyPropertyChanged(nameof(IsSelected)); } }
}

然后是列表和按钮点击方法的示例实现:

public partial class MainWindow : Window
{
    public ObservableCollection<Foo> Foos { get; set; } 
        = new ObservableCollection<Foo>() { new Foo() { FooName = "A1" }, new Foo { FooName = "A2" }, new Foo() { FooName = "A3" } };
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        foreach (var foo in Foos)
            foo.IsSelected = false;
        foreach (var foo in Foos)
            if (foo.FooName == (sender as Button)?.Tag as string)
                foo.IsSelected = true;
    }
}