I have a strange problem with a ListBox: I have bound it to a Collection that does not implement INotifyCollectionChanged (Not possible as it's items are dynamically generated on request):
IEnumerator IEnumerable.GetEnumerator()
{
foreach (var metaData in Metadata.Where((m) => m.IsEnabled))
{
yield return new DynamicPropertyValue(this, metaData);
}
}
Therefore, when IsVisible of the ListBox changes, I'm trying to force to update the ItemsSource by setting it to Null and then update the binding:
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");
}
}
}
}
When the ItemsSource is set to Null, the ItemsControl does not contain any items any more and the Items collection is empt, as expected. However, when applying the binding again, all old items are restored. The Items collection contains the same instances as before. The GetEnumerator method is called, but the new items are ignored.
I don't understand why this is the case or how I can avoid that the ItemsControl caches its Items.
Alex
I stumbled across your post trying to figure out how to accomplish much the same thing. Not wanting to use reflection, I kept on researching and found a better answer. :)
One of the things I am still trying to get used to is how so many features in WPF are accessed not via direct calls to members of the object you're interested in, but in calls to static members which do some behind-the-scenes magic to accomplish the goal.
If I understand your scenario correctly, yours is one of those cases. In particular, while you found that getting the CollectionView
object via reflection accomplished your goal, the "right" way to do this is to use the CollectionViewSource
class to retrieve the CollectionView
for the bound object.
Without a more complete code example, I can't say what the exact code in your scenario would look like. But the basic idea is to do something like this:
CollectionViewSource.GetDefaultView(itemsSourceObject).Refresh();
I.e. this looks up the default view for the object bound to the ItemsSource
property (that is, it assumes a variable named itemsSourceObject
and passes its value to the method), and then of course calls the Refresh()
method to update the view.