【问题标题】:WPF Collections and DatabindingWPF 集合和数据绑定
【发布时间】:2011-01-03 02:32:06
【问题描述】:

我是 WPF 的新手,并试图围绕 WPF 的框架,它为您做什么和不做什么。

为了澄清这一点,我想知道这之间有什么区别:

public List<MyCustomObject> MyCustomObjects
{
    get { return (List<MyCustomObject>)GetValue(MyCustomObjectsProperty); }
    set { SetValue(MyCustomObjectsProperty, value); }
}

public static readonly DependencyProperty MyCustomObjectsProperty =
    DependencyProperty.Register("MyCustomObjects", typeof(List<MyCustomObject>),
    typeof(Main), new UIPropertyMetadata(new List<MyCustomObject>()));



还有这个:

public ObservableCollection<MyCustomObject> MyCustomObjects { get; set; }

public Main ()
{
    MyCustomObjects = new ObservableCollection<<MyCustomObject>();
}

【问题讨论】:

  • 感谢大家的回答。 Cwap 似乎对我来说最清楚,所以我和他一起去了,但我都投了赞成票。再次感谢!

标签: wpf data-binding binding collections


【解决方案1】:

1:

您正在使用依赖属性来“告诉”框架何时更改该属性。这将对您的绑定产生以下影响:

MyCustomObjects.Add(new MyCustomObject()); //Wont update the view through databinding
MyCustomObjects = new List<MyCustomObject>(); //Will update the view through databinding

您可以通过在哪个类公开属性上实现 INotifyPropertyChanged 来获得相同的数据绑定功能,但依赖属性的功能不仅仅是通知更改。不过,这些都是相当高级的功能,您不太可能在普通的 joe 应用程序中遇到这些功能:)

2:

您正在使用一个可观察的集合,它为您实现了INotifyCollectionChanged,以便在集合的内容发生变化时通知数据绑定。这将产生与#1相反的后果:

MyCustomObjects.Add(new MyCustomObject()); //Will update the view through databinding
MyCustomObjects = new ObservableCollection<MyCustomObject>(); //Won't update the view through databinding

【讨论】:

  • 如果我做一个属于 DependencyProperty 的 ObserverableCollection,我会得到两者吗?这是个好主意吗?
  • 你会得到两个,是的。如果这是一个好主意取决于您的需求,但我经常实现它(尽管我更喜欢使用 INotifyPropertyChanged,因为它更简单)。
  • 由于 OP 批准了答案,我冒昧地对其进行编辑以纠正一些不准确之处(INotifyPropertyChanged -> INotifyCollectionChanged 等)
  • 看起来不错的 Aviad。抱歉不正确。像往常一样打字太快了:)
【解决方案2】:

除了 Aviad 和 Reed 的回答,我想指出您的第一个代码示例中的一个严重错误:

public static readonly DependencyProperty MyCustomObjectsProperty =
    DependencyProperty.Register("MyCustomObjects", typeof(List<MyCustomObject>),
    typeof(Main), new UIPropertyMetadata(new List<MyCustomObject>()));

用作默认值的new List&lt;MyCustomObject&gt;()只会创建一次,因此默认情况下,您类型的所有实例都将共享相同的List&lt;MyCustomObject&gt; 实例,这可能不是您想要的。 .. 这里唯一合理的默认值是null

【讨论】:

  • 如此真实,也是新手常见的错误。小心这个!
  • 嗯,恐怕我不明白...我想要一个 MyCustomObjects 列表。我没有创建多个 MyCustomObjects 变量的实例(您引用了“所有实例”,但我不会只在我的属性中声明一个实例)。我希望你能回复,因为我知道这很重要,但我就是不明白。
  • 同一个列表实例将被所有Main 类型的对象共享(除非另有明确指定)。
  • 啊.. 我想我明白了。我没有遇到问题,因为 Main 对我来说是一个单实例类。如果我有多个 Main 实例,那么它们将共享同一个“列表”实例。我可以看到这如何导致令人讨厌的难以发现的问题。感谢 Thomas 和 Avaid 的提示。
【解决方案3】:

好的,我们必须整理一下,这里有几个概念混在一起。

首先,您要问的是字段支持属性和依赖属性之间的区别。 Google 将是您最好的朋友,但我推荐 WPF 先锋 Josh Smith 的这篇博文:Overview of dependency properties in WPF

简而言之:依赖属性支持 WPF 的丰富性:样式、动画、绑定、元数据等等。

其次,您要问的是ListObservableCollection 之间的区别。后者提供关于集合的任何更改(添加、删除、更改顺序、清除等)的更改通知(以事件的形式),而前者没有。你可以在这里阅读更多信息:The ObservableCollection Class

简而言之:ObservableCollection 提供 UI 自动反映视图模型中的更改所需的更改通知。

【讨论】:

    【解决方案4】:

    在第一种情况下,您要设置一个包含 List&lt;T&gt; 实例的依赖属性。

    在第二个中,您将创建一个普通的 CLR 属性,但将其设置为 ObservableCollection&lt;T&gt;

    对于 WPF 数据绑定,这里有一些区别。

    通常,您希望 DataContext 中的所有属性(默认情况下,它是“绑定”到的对象)实现 INotifyPropertyChanged 或成为依赖属性。这让绑定框架知道何时对该对象进行了更改。但是,通常情况下,如果您使用自定义控件,您只会使用依赖属性 - 通常最好将您的数据绑定到的对象作为一个单独的类,分配给 DataContext。 (详情请见Josh Smith on MVVMmy recent detailed post on MVVM...)

    但是,对于集合,您通常还希望绑定系统知道集合中的项目何时更改(即:添加了一个项目)。 ObservableCollection&lt;T&gt; 通过实现 INotifyCollectionChanged 来处理这个问题。

    通过使用第二种方法(使用 ObservableCollection&lt;T&gt;),您的 UI 可以判断何时从集合中添加或删除项目 - 而不仅仅是分配新集合的时间。这可以让事情自动运行,例如在将新项目添加到您的集合时添加元素的 ListBox。

    【讨论】:

      猜你喜欢
      • 2011-05-14
      • 1970-01-01
      • 1970-01-01
      • 2021-01-31
      • 2011-07-11
      • 1970-01-01
      • 2019-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多