2014-10-01 92 views
0

的内容我有一个奇怪的问题,一个ListBox: 我把它绑定到不实现INotifyCollectionChanged(不可能的,因为它的项目要求动态生成)的集合:列表框不更新的ItemsSource

IEnumerator IEnumerable.GetEnumerator() 
{ 
    foreach (var metaData in Metadata.Where((m) => m.IsEnabled)) 
    { 
     yield return new DynamicPropertyValue(this, metaData); 
    } 
} 

因此,当ISVISIBLE的ListBox的变化,我试图武力将其设置为null,以更新的ItemsSource然后更新绑定:

static void ItemsControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) 
{ 
    if (true.Equals(e.NewValue)) 
    { 
     var element = (ItemsControl)sender; 
     var bindingExpression = BindingOperations.GetBindingExpression(element, ItemsControl.ItemsSourceProperty); 
     if (bindingExpression != null) 
     { 
      element.SetCurrentValue(ItemsControl.ItemsSourceProperty, null); 
      bindingExpression.UpdateTarget(); 

      var count = element.ItemsSource.OfType<object>().Count(); 
      if (count != element.Items.Count) 
      { 
       Debug.WriteLine("Wrong number of items"); 
      } 
     } 
    } 
} 

当的ItemsSource设置为null,ItemsControl的呢不含如预期的那样,任何物品都已被取消,并且Items集合已被清空。但是,再次应用绑定时,所有旧项目都会恢复。 Items集合包含与之前相同的实例。 GetEnumerator方法被调用,但新项目被忽略。

我不明白为什么这是这种情况,或者我可以如何避免ItemsControl缓存它的项目。

亚历

+1

为什么不只是创建一个新的集合并将其分配给ItemSource属性? – Clemens 2014-10-01 08:18:27

+0

'element.SetCurrentValue(ItemsControl.ItemsSourceProperty,null);'我相信这只会将您的'ItemsControl.ItemSource'设置为'null',您的代码在哪里更新集合? – Bolu 2014-10-01 08:30:06

+0

集合可以在多个(未连接的)对象上共享。当我在一个位置替换它时,我将不得不在任何地方替换它。但我无法访问所有这些地方。 – LionAM 2014-10-01 08:33:51

回答

1

我偶然发现你的文章试图找出如何完成同样的事情。不想使用反思,我一直在研究并找到更好的答案。 :)

我仍然试图去习惯的一件事情是WPF中的如此多功能是如何访问的,而不是通过直接调用您感兴趣的对象的成员,而是调用静态成员一些幕后的魔法来实现这一目标。

如果我正确理解您的方案,那么您就是其中一种情况。特别是,虽然您发现通过反射获取对象实现了目标,但“正确”的方法是使用CollectionViewSource类为绑定对象检索CollectionView

没有一个更完整的代码示例,我不能说你的方案中的确切代码是什么样子。但基本的想法是做这样的事情:

CollectionViewSource.GetDefaultView(itemsSourceObject).Refresh(); 

即,这将查找绑定到ItemsSource属性的对象的默认视图(即,它假定一个名为itemsSourceObject的变量并将其值传递给方法),然后调用Refresh()方法更新视图。

+0

谢谢。有用。你是怎样找到它的?你知道如果有多个ListBox实例(具有相同的ItemsSource)会发生什么?都更新 - 或只有其中一个...... – LionAM 2015-03-03 14:03:46

+0

@LionAM:我真的不记得我是如何找到它的。我确定我正在寻找“CollectionView”和其他一些关键词,但我不记得具体细节。如果集合绑定到多个'ItemsControl'('ListBox'或其他),则全部都应该更新。 – 2015-03-04 01:00:04

+0

@LionAM:请注意,这仅适用于您直接绑定集合(导致WPF使用默认视图)的情况;如果你明确地创建了你自己的视图,那么显然这个视图被用来代替默认视图,而你需要刷新那个视图。当然,在这种情况下,由于自己创建了视图,因此更容易找到(即自己存储引用):) – 2015-03-04 01:00:41

0

作为ListBox.Items.Refresh()不具有所期望的效果,我试图在下层的CollectionView刷新。而且 - 列表框更新。与此问题,但是,是唯一的方法访问此的CollectionView,采用反射,作为物业是内部:

var collectionViewProperty = typeof (ItemCollection).GetProperty("CollectionView", BindingFlags.Instance | BindingFlags.NonPublic); 
var collectionView = (CollectionView) collectionViewProperty.GetValue(itemsControl.Items); 
collectionView.Refresh(); 

看来,的CollectionView缓存为与ItemsControl的使用的每个的ItemsSource。有什么方法可以改变这种行为吗?