【问题标题】:Dependency Property Update Mechanism依赖属性更新机制
【发布时间】:2012-11-27 19:12:13
【问题描述】:

我有一个自定义控件,其中定义了一个依赖属性,并且我的控件实现了 INotifyPropertyChanged 接口。

依赖属性是自定义对象的集合。

场景 1

DP 属于 List 类型,无论我在列表中进行什么更改,MainUI 中都没有更新,因为我相信 WPF 不理解在列表中添加和删除对象。它理解全新的引用,因此每当我想更新我使用的控件列表时,它都会实现这一目标

MyProperty=new List();

在这种方法中,我的 DP 回调每次都会触发,但 eventArgs.NewValue 始终保持为零(它正确更新了 UI 上的列表)但是因为我需要在基于 e.NewItems.Count 的属性更改回调中编写一些逻辑,在此没有工作的案例。请告诉我为什么 e.NewItems 不起作用。

场景 2

DP 属于 ObservableCollection 类型,因此作为我绑定 DP 的视图模型中的集合属性。在这种情况下,我的属性更改回调根本不会触发,因为在第一次初始化属性后我再也没有使用“new”关键字。 UI 更新但属性更改仍未触发。所以我在属性更改回调中的逻辑不会被执行。

我应该如何让它们中的任何一个或两个都工作。

【问题讨论】:

  • 错了。 INotifyPropertyChanged 用于常规(非 DependencyObject)POCO 对象。您不需要在自定义控件中实现它。
  • @HighCore 同意你的观点,我的错。但是删除它并不能解决实际问题。请帮帮我。

标签: c# wpf dependency-properties


【解决方案1】:

我会使用 ObservableCollection 方法,并订阅它的 CollectionChanged 事件。
这样,只要集合发生更改,您就会收到通知。

但其他方法也应该有效。当您将常规列表设置为新实例时,将为依赖属性触发 PropertyChangedCallback,通过检查 DependencyPropertyChangedEventArgs 对象,您可以获得新值。

XAML:

<StackPanel>
    <Button Content="Add to observablecollection" Click="click1" />
    <Button Content="Set list to new instance" Click="click2" />
</StackPanel>

代码隐藏:

public partial class Window1 : Window
{
    public ObservableCollection<string> Strings { get; set; }

    public List<string> StringsList
    {
        get { return (List<string>)GetValue(StringsListProperty); }
        set { SetValue(StringsListProperty, value); }
    }

    public static readonly DependencyProperty StringsListProperty =
        DependencyProperty.Register("StringsList", typeof(List<string>), typeof(Window), new PropertyMetadata(null, StringsListPropertyChanged));

    public Window1()
    {
        InitializeComponent();

        Strings = new ObservableCollection<string>();
        Strings.CollectionChanged += strings_CollectionChanged;

        StringsList = new List<string> { "Test1", "Test2", "Test3", "Test4" };
    }

    void strings_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        //Fires everytime the observablecollection has an item added/removed etc.
        MessageBox.Show(string.Format("ObservableCollection has changed! Count is now {0}", this.Strings.Count.ToString()));

        if (this.Strings.Count == 10)
            Console.WriteLine("Collection contains 10 strings!!");
    }

    private static void StringsListPropertyChanged(DependencyObject e, DependencyPropertyChangedEventArgs args)
    {
        var newCount = ((List<string>)args.NewValue).Count.ToString();
        MessageBox.Show(string.Format("Dependency property has changed! Count is now {0}", newCount));
    }

    private void click1(object sender, RoutedEventArgs e)
    {
        this.Strings.Add("Test1");
    }

    private void click2(object sender, RoutedEventArgs e)
    {
        this.StringsList = new List<string> { "Newitem1", "Newitem2" };
    }
}

【讨论】:

  • 感谢您的回答,但问题是如果我采用 ObservableCollection 方式并订阅 CollectionChanged 事件,它不仅会在每次更改集合时执行,而且会针对集合中的每个项目执行。如果我的集合有 100 条记录,则此事件将执行 100 次,因此此事件不是在其中运行任何逻辑的好地方,因为我不想多次执行该逻辑。并且对于属性更改的其他方法,它为 eventargs.new 项目提供 null。
  • 不,每次添加或删除项目时都会引发一次 CollectionChanged 事件。如果您在集合中有 100 个项目,并且再添加一个,则它不会被提升 101 次只是 1。如果 DependencyPropertyChangedEventArgs 上的 NewValue 属性对您来说为空,那么您做错了。你试过我写的代码吗?
【解决方案2】:

ObservableCollection 继承自 INotifyPropertyChanged 和 INotifyCollectionChanged。我认为如果您想知道集合何时更改,您应该使用此接口:

INotifyCollectionChanged

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多