如何使GradientStopCollection可观察?

时间:2018-03-20 13:23:34

标签: xaml data-binding collections observablecollection inotifypropertychanged

我遇到了一个问题,我想在列表框中显示渐变停止列表。问题是将gradientstops放在ObservableCollection类型的集合中,但是使用GradientStopCollection不行。

当我使用GradientStopCollection时,会显示窗口初始化之前列表中的项目,但是当按下按钮添加第三个项目时,UI不会更新。 调用OnPropertyChanged不会导致UI更新。我举了一个小例子试图重现这个问题。 那么即使我使用了gradientstop集合,如何让窗口正确更新呢?

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>

1 个答案:

答案 0 :(得分:0)

我认为没有任何简单的方法解决这个问题。

您可以创建自己的集合类,继承自GradientStopCollection并实现接口INotifyCollectionChanged,从而有效地创建ObservableGradientStopCollection。

你可以找到一个INotifyCollectionChanged的实现作为一个exmple。

这可能更容易,只是为了保留两个集合,虽然它看起来很糟糕。