【问题标题】:Setting ItemsSource before or after adding items changes object?在添加项目更改对象之前或之后设置 ItemsSource?
【发布时间】:2012-08-05 18:07:30
【问题描述】:

我遇到了一个奇怪的情况,我实现了一个 ObservableConcurrentDictionary(基于 .NET 的 ConcurrentDictionary),我曾经用它来实现 ObservableConcurrentCollection(它只是自动设置 Dictionary 中的 Key 属性,并具有所有 IList、IEnumerable、IQueryable 和 ICollection 方法)。当我执行以下操作时,一切正常:

ObservableConcurrentCollection<string> items = new ObservableConcurrentCollection<string>();
dataGrid.ItemsSource = items;
items.Add("TEST");

这在 DataGrid 中得到了完美体现。

但是,当我这样做时:

ObservableConcurrentCollection<string> items = new ObservableConcurrentCollection<string>();
items.Add("TEST"); // <-- Notice that this and the line below are swapped.
dataGrid.ItemsSource = items;

它无法正常工作,因为“项目”中的项目突然变成了 KeyValuePair。我可以通过在最后一行中使用 dataGrid.ItemsSource = items.Values 轻松解决此问题,但我宁愿让它像上一个一样工作(而且它也令人困惑)。

【问题讨论】:

  • 如果没有看到 ObservableConcurrentCollection 的实现,真的很难对此发表评论。但问题可能出在您的Indexer
  • 代码并没有什么特别之处,ObservableConcurrentDictionary 只是 ConcurrentDictionary 的包装器,带有 OnCollectionChanged 事件。 ObservableConcurrentCollection 使用标准的 IList 内容(自动获取和设置 ObservableConcurrentDictionary 的键)加上 IEnumerable 和 Indexer 更改为值。但是 ObservableConcurrentCollection 的索引器甚至没有被调用。

标签: c# wpf data-binding binding itemssource


【解决方案1】:

由于您的新 ObservableConcurrentDictionary 类基于 ConcurrentDictionary,我怀疑问题出在接口方法之一的实现中。

没有看到该类,很难诊断,但我怀疑问题出在返回整个字典条目而不是键指定的值的检索实现中。

例如,当 ItemsSource 在第二种情况下绑定到网格时,它可能会通过 IEnumerable 检索值,而当您在第一种情况下调用 Add 时,它会触发包含正确信息的 observable 事件。

通过在可疑的检索方法中放置断点或在分配 ItemsSource 的第二种情况下单步执行代码来找出问题发生的位置应该相当简单。这应该会很快向您显示正在执行的方法,并显示正在返回的是字典条目而不是值。

【讨论】:

  • 我很确定我已经实现了大多数方法,找不到其他任何方法。我在这里上传了课程:pastebin.com/TDuTGS1z + pastebin.com/Y9bVzNAD
  • 基于这些类,问题似乎很可能是 IQueryable 接口,因为这是在第二种情况下用于填充网格项的接口。不幸的是,我对 linq 表达式的了解还不够,无法就如何解决此问题提供足够的指导,而且 MSDN 帮助在此界面上也没有太大帮助。
  • 是的,但是 IQueryable 只是 GetEnumerator,甚至在 ObservableConcurrentDictionary 中都没有调用它,所以我怀疑在第二种情况下使用了 IQueryable。我还尝试覆盖 ToArray 方法以使用类型 T 而不是 KeyValuePair 但也没有调用它。我有点困惑该怎么做,MSDN 上的文档非常糟糕,ItemsSource 到底在做什么。
  • 如果您在设置后在调试器中查看 ItemsSource 并展开 Raw 部分,您将看到各种 iqueryable 接口。似乎 iqueryable 或 ienumerable 以某种方式返回字典条目而不是字符串值,但我无法让它在集合/字典方法中中断以准确说明发生了什么。抱歉,我无法在这方面提供更多帮助。
【解决方案2】:

对我来说,我总是用这个

<DataGrid ItemsSource="{Binding}" x:Name="datagrid" >

然后

ObservableConcurrentCollection<string> items = new ObservableConcurrentCollection<string>();
items.Add("TEST"); 
dataGrid.DataContext = items;

你可以试试这个,即使我换了台词也对我有用

【讨论】:

    【解决方案3】:

    通过更改 ObservableConcurrentCollection 解决了这个问题,我删除了继承并为 ObservableConcurrentDictionary 创建了一个字段。现在就像一个魅力。

    【讨论】:

      猜你喜欢
      • 2017-04-06
      • 2016-05-10
      • 2011-03-23
      • 2014-05-25
      • 2016-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-29
      相关资源
      最近更新 更多