我对ListBox有一个奇怪的问题: 我已将它绑定到未实现INotifyCollectionChanged的Collection(不可能,因为它的项目是根据请求动态生成的):
IEnumerator IEnumerable.GetEnumerator()
{
foreach (var metaData in Metadata.Where((m) => m.IsEnabled))
{
yield return new DynamicPropertyValue(this, metaData);
}
}
因此,当ListBox的IsVisible发生变化时,我试图通过将ItemsSource设置为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集合是empt,正如预期的那样。但是,再次应用绑定时,将还原所有旧项目。 Items集合包含与以前相同的实例。调用GetEnumerator方法,但忽略新项目。
我不明白为什么会这样,或者我怎么能避免ItemsControl缓存其项目。
亚历
答案 0 :(得分:2)
我偶然发现了你的帖子,试图弄清楚如何完成同样的事情。不想使用反射,我继续研究并找到了更好的答案。 :)
我仍在尝试习惯的一件事是,如何通过直接调用您感兴趣的对象的成员来访问WPF中的这么多功能,而是调用静态成员执行某些操作实现目标的幕后魔术。
如果我理解你的情况正确,你的情况就是其中之一。特别是,当你发现通过反射获得CollectionView
对象完成了你的目标时,&#34;对&#34;这样做的方法是使用CollectionViewSource
类来检索绑定对象的CollectionView
。
如果没有更完整的代码示例,我无法说出您的方案中的确切代码是什么样子。但基本的想法是做这样的事情:
CollectionViewSource.GetDefaultView(itemsSourceObject).Refresh();
即。这会查找绑定到ItemsSource
属性的对象的默认视图(也就是说,它假定一个名为itemsSourceObject
的变量并将其值传递给方法),然后当然调用{{1更新视图的方法。
答案 1 :(得分:0)
由于ListBox.Items.Refresh()
没有达到预期效果,我尝试在底层CollectionView上刷新。并且voilà - ListBox更新。但问题是,访问此CollectionView的唯一方法是使用Reflection,因为属性是内部的:
var collectionViewProperty = typeof (ItemCollection).GetProperty("CollectionView", BindingFlags.Instance | BindingFlags.NonPublic);
var collectionView = (CollectionView) collectionViewProperty.GetValue(itemsControl.Items);
collectionView.Refresh();
似乎为与ItemsControl一起使用的每个ItemsSource缓存了CollectionView。有没有办法改变这种行为?