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;
}
}
我有一个 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;
}
}