【问题标题】:Custom UIElement does not update layout when an ObservableCollection changes through binding当 ObservableCollection 通过绑定更改时,自定义 UIElement 不会更新布局
【发布时间】:2015-05-02 13:40:04
【问题描述】:

再次遇到一个(可能)简单的问题。

我想创建一个自定义 UIElement(保持正交的线条集合)。 此 UIElement 在我的 MVVM 应用程序中用作视图。

这是我的代码:

class RaOrthogonalLine : Canvas, INotifyPropertyChanged
    {
        public RaOrthogonalLine()
        {
            Points.CollectionChanged += Points_CollectionChanged;
        }

        void Points_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Paint();
        }

        void Paint()
        {
             //PaintingStuff! Here I would like to get in!
        }

        void newLine_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (LineClicked != null)
                LineClicked(sender, e);
        }

        public delegate void LineClickedEventHandler(object sender, MouseButtonEventArgs e);
        public event LineClickedEventHandler LineClicked;

        public ObservableCollection<RaPoint> Points
        {
            get
            {
                return (ObservableCollection<RaPoint>)GetValue(PointsProperty);
            }
            set
            {
                SetValue(PointsProperty, value);
                RaisePropertyChanged("Points");
            }
        }
        public static readonly DependencyProperty PointsProperty = DependencyProperty.Register("Points", typeof(ObservableCollection<RaPoint>), typeof(RaOrthogonalLine),
            new FrameworkPropertyMetadata(new ObservableCollection<RaPoint>(), new PropertyChangedCallback(PointsPropertyChanged))
        {
            BindsTwoWayByDefault = true,
            DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
        }
        );

        private static void PointsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RaOrthogonalLine thisLine = (RaOrthogonalLine)d;
            thisLine.Paint();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

    }

在我的 XAML 中,我将 ViewModel 的 ObservableCollection 绑定到 UIElement(View) 中的 ObservableCollection。

效果很好。

我现在的问题是当集合更改(添加/删除/..)时我没有收到通知 - 因为那时我需要重新绘制它。

我试图获取 Points.CollectionChanged 事件,但它没有触发。

有人有想法吗?

谢谢!

【问题讨论】:

  • WPF中没有“Paint”之类的东西,你的代码都是错误的。删除所有内容并使用ItemsControl。开始阅读here

标签: c# wpf mvvm observablecollection uielement


【解决方案1】:

问题是您在控件的构造函数中添加了CollectionChanged 事件处理程序。在构造函数中,您的 Paint 属性尚未绑定到正确的源(实际上它具有 PointsProperty 的默认值,即一个空集合)。

您应该在PointsPropertyChanged 方法中添加和删除事件处理程序。看看这个示例代码:

public class RaOrthogonalLine : Canvas
{
    public INotifyCollectionChanged Points
    {
        get { return (INotifyCollectionChanged)GetValue(PointsProperty); }
        set { SetValue(PointsProperty, value); }
    }


    public static readonly DependencyProperty PointsProperty =
        DependencyProperty.Register("Points", typeof(INotifyCollectionChanged), typeof(RaOrthogonalLine),
        new FrameworkPropertyMetadata(null, new PropertyChangedCallback(PointsPropertyChanged))
        {
            BindsTwoWayByDefault = true,
            DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
        });

    void Points_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        Paint();
    }

    private static void PointsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        RaOrthogonalLine raOrthogonalLine = (RaOrthogonalLine)d;
        INotifyCollectionChanged newValue = (INotifyCollectionChanged)e.NewValue;
        INotifyCollectionChanged oldValue = (INotifyCollectionChanged)e.OldValue;

        if (oldValue != null)
        {
            oldValue.CollectionChanged -= raOrthogonalLine.Points_CollectionChanged;
        }

        if (newValue != null)
        {
            newValue.CollectionChanged += raOrthogonalLine.Points_CollectionChanged;
        }
        raOrthogonalLine.Paint();
    }
}

我希望它可以帮助你解决你的问题。

【讨论】:

    【解决方案2】:

    这可能与依赖属性有关,但这对我来说很好。
    您确定要在集合中添加和移除(而不是替换集合)吗?

    public class Points
    {
        void Strings_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Debug.WriteLine("Strings_CollectionChanged");
        }
        private ObservableCollection<string> strings = new ObservableCollection<string>();
        // I think you are better off with just a get 
        public ObservableCollection<string> Strings { get { return strings; } }
        public Points()
        {
            Strings.CollectionChanged += new NotifyCollectionChangedEventHandler(Strings_CollectionChanged);
            Strings.Add("new one");
            Strings.Add("new two");
            Strings.RemoveAt(0);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-20
      • 2016-05-19
      • 2012-02-29
      相关资源
      最近更新 更多