我遇到了一个问题,我想在列表框中显示渐变停止点列表。问题在于,将梯度停止点放在 ObservableCollection 类型的集合中是有效的,但使用 GradientStopCollection 则不然。
当我使用 GradientStopCollection 时,将显示初始化窗口之前列表中的项,但是当按下按钮添加第三个项时,UI 不会更新。调用 OnPropertyChanged 不会导致 UI 被更新。我举了一个小例子来尝试重现这个问题。那么,即使我使用渐变停止集合,如何才能让窗口正确更新呢?
using System.Windows;
using System.Windows.Media;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new ViewModel();
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
ViewModel vm = (DataContext as ViewModel);
vm.Collection.Add(new GradientStop(Colors.Red, 0.5));
//This line has no effect:
vm.OnPropertyChanged("Collection");
}
}
}
视图模型:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace WpfApp1
{
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public GradientStopCollection Collection
{
get
{
return collection;
}
set
{
collection = value;
}
}
//Replacing GradientStopCollection
// with ObservableCollection<GradientStop> makes it work
GradientStopCollection collection;
public ViewModel()
{
GradientStop a = new GradientStop(Colors.Green, 0);
GradientStop b = new GradientStop(Colors.Yellow, 1.0);
collection = new GradientStopCollection() { a, b } ;
OnPropertyChanged("Collection");
}
public void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class Converter : IValueConverter
{
public object Convert(object value, Type targettype, object parameter, CultureInfo cultureInfo)
{
if (value is Color color)
return new SolidColorBrush(color);
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targettype, object parameter, CultureInfo cultureInfo)
{
throw new NotImplementedException();
}
}
}
最后是 xaml:
<Grid>
<Grid.Resources>
<local:Converter x:Key="ColorConverter"/>
<DataTemplate DataType="{x:Type GradientStop}">
<TextBlock
Width="50"
Background="{Binding Color, Converter={StaticResource ColorConverter}}"
Text="block"
/>
</DataTemplate>
</Grid.Resources>
<ListBox
x:Name="GradientListBox"
Width="72"
Height="92"
ItemsSource="{Binding Collection}" />
<Button Content="Button" HorizontalAlignment="Left" Margin="169,264,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
没有任何简单的方法来解决这个问题。
您可以创建自己的集合类,从 GradientStopCollection 继承并实现接口 INotifyCollectionChanged,从而有效地制作 ObservableGradientStopCollection。
您可能会找到INotifyCollectionChanged的实现作为示例。
保留两个集合可能会更容易,尽管这看起来很糟糕。