简体   繁体   中英

How can I get an ItemsSource as an ObservableCollection<>?

I'm trying to modify a property of a grid depending on whether or not there are any items in the ObservableCollection<> the ItemsSource is bound to. I currently have an event for OnItemsSourceChanged on the grid, but the problem is that ItemsSource is an object, and without casting it, I don't have access to the CollectionChanged event of the ObservableCollection<> . The generic type of ObservableCollection<> is undetermined until runtime and can be many things.

I've tried casting it with ItemsSource as ObservableCollection<object> , but that returns null. No luck with ItemsSource as ObservableCollection<dynamic> , either. Doing ItemsSource as IEnumerable<object> works surprisingly enough, but that still does not allow me to access the CollectionChanged event.

How can I cast my object to the underlying ObservableCollection<> ? I'd prefer to avoid using reflection, but I'm not going to be picky here.

What about casting it to INotifyCollectionChanged?

EDIT:

What you probably should be doing is something like this:

<TextBlock Visibility="{Binding MyObservableCollection.Count, Converter={StaticResource NonZeroToVisibleConverter}}">

Where NonZeroToVisibleConverter is something like:

public class ColorConverter : IValueConverter
{
  public object Convert(object value, Type targetType, 
      object parameter, CultureInfo culture)
  {   
    return (int)value > 0 ? Visibility.Visible : Visibility.Collapsed
  }

  public object ConvertBack(object value, Type targetType, 
      object parameter, CultureInfo culture)
  {
    throw new NotImplmentedException();
  }
}

OR probably even better

<Grid Name="MyGrid" ItemsSource="{Binding MyObservableCollection" />

<TextBlock Visibility="{Binding HasItems, ElementName=MyGrid, Converter={StaticResource BoolToVisibilityConverter}}" />

Last Resort For Future Reference

Your last resort would of been better to expose a property ShouldBe/IsVisible in you ViewModel and and bind to that in your View.

Consider the following code:

// where 
ObservableCollection<Foo> foo = new();
element.ItemsSource = foo;
// then negotiate to non-generic types
var bar = element.ItemsSource as INotifyCollectionChanged;
bar.CollectionChanged += (NotifyCollectionChangedEventHandler)(delegate(object sender, NotifyCollectionChangedEventArgs e) 
{
  var collection = bar as ICollection;
  // TODO: handle based on collection.Count
});

This way you are able to handle the event regardless of the generic types applied to ObservableCollection<T> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM