如何使 GradientStopCollection 可观察



我遇到了一个问题,我想在列表框中显示渐变停止点列表。问题在于,将梯度停止点放在 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的实现作为示例。

保留两个集合可能会更容易,尽管这看起来很糟糕。

相关内容

  • 没有找到相关文章

最新更新