4

I have the following test code:

private class SomeItem
    {
       public string Title{ get{ return "something"; } }
       public bool Completed { get { return false; } set { } }
    }

    private class SomeCollection : IEnumerable<SomeItem>, INotifyCollectionChanged
    {
        private IList<SomeItem> _items = new List<SomeItem>();
        public void Add(SomeItem item)
        {
            _items.Add(item);
            CollectionChanged(this, new 
             NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        #region IEnumerable<SomeItem> Members

        public IEnumerator<SomeItem> GetEnumerator()
        {
            return _items.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _items.GetEnumerator();
        }

        #endregion

        #region INotifyCollectionChanged Members

        public event NotifyCollectionChangedEventHandler CollectionChanged;

        #endregion
    }

    private SomeCollection collection = new SomeCollection();

    private void Expander_Expanded(object sender, RoutedEventArgs e)
    {
        var expander = (Expander) sender;
        var list = expander.DataContext as ITaskList;
        var listBox = (ListBox)expander.Content;
        //list.Tasks.CollectionChanged += CollectionChanged;
        collection.Add(new SomeItem());
        collection.Add(new SomeItem());
        listBox.ItemsSource = collection;
    }

and the XAML

<ListBox Name="taskListList" ItemsSource="{Binding}" BorderThickness="0" ItemContainerStyle="{StaticResource noSelectedStyle}" >
    <ListBox.ItemTemplate>
        <DataTemplate>
           <Expander Expanded="Expander_Expanded">
              <Expander.Header>
                <StackPanel Orientation="Horizontal">
                  <TextBlock Text="{Binding Name}" />
                  <TextBox KeyUp="TextBox_KeyUp" Width="200"/>
                  <Button Name="hide" Click="hide_Click">
                      <TextBlock Text="hide" />
                  </Button>
                </StackPanel>
               </Expander.Header>
                  <ListBox Name="taskList" ItemsSource="{Binding}" ItemTemplate=" 
                     {StaticResource taskItem}" />
              </Expander>
         </DataTemplate>
      </ListBox.ItemTemplate>
   </ListBox>

the outer listbox gets populated on load. when the expander gets expanded I then set the ItemsSource property of the inner listbox (the reason i do this hear instead of using binding is this operation is quite slow and i only want it to take place if the use chooses to view the items). The inner listbox renders fine, but it doesn't actually subscribe to the CollectionChanged event on the collection. I have tried this with ICollection instead of IEnumerable and adding INotifyPropertyChanged as well as replacing INotifyCollectionChanged with INotifyPropertyChanged. The only way I can actually get this to work is to gut my SomeCollection class and inherit from ObservableCollection<SomeItem>. My reasoning for trying to role my own INotifyCollectionChanged instead of using ObservableCollection is because I am wrapping a COM collection in the real code. That collection will notify on add/change/remove and I am trying to convert these to INotify events for WPF.

Hope this is clear enough (its late).

Naser Asadi
  • 1,085
  • 16
  • 34
  • 1
    I'm guessing it's because you don't sufficiently implement `INotifyCollectionChanged` behavior, and you don't implement `INotifyPropertyChanged` at all. It's probably not worth investigating to find the specific reasons, as you are better off just changing `SomeCollection` to inherit from `ObservableCollection` and getting a lot of it done for you. Why reinvent the wheel? You'll still be able to override methods to customize its behavior if you need. – Sean Hanley Dec 30 '11 at 17:42
  • Have you got more details on the COM collection you are trying to wrap? I think you should be asking how to convert your COM collection an an ObservableCollection. – Iain Nov 29 '13 at 07:16

2 Answers2

0

ObservableCollection<T> also implements INotifyPropertyChanged. As you collection is simply an IEnumerable<T> you don't have any properties to create events for, but ObservableCollection<T> create PropertyChanged events for the Count and Item[] properties. You could try to make your collection more like ObservableCollection<T> by deriving from IList<T> and implementing INotifyPropertyChanged. I don't know if that will fix your problem, though.

Martin Liversage
  • 96,855
  • 20
  • 193
  • 238
  • 1
    If I understand the question correctly the collection already exists and has a base class that is not ObserverableCollection. This collection, even though it implements INotifyCollectionChanged, does not force an update of the list box when it is modified. The question is why? – Martin Liversage Jul 24 '09 at 15:28
0

I don't understand why I keep seeing people trying to implement their own collections in WPF. Just use an ObservableCollection<SomeItem> and all your CollectionChanged notifications will be taken care of.

private ObservableCollection<SomeItem> collection = 
    new ObservableCollection<SomeItem>();

If you want something to happen on SomeItem.PropertyChanged, make SomeItem implement INotifyPropertyChanged

As for why your CollectionChanged isn't being raised, you are setting the ItemsSource property, not binding it. Setting it means you are making a copy of collection and storing it in ListBox.ItemsSource. Binding it means you would be telling ListBox.ItemsSource to refer to collection for it's data.

Rachel
  • 122,023
  • 59
  • 287
  • 465
  • well, ObservableCollection doesn't implement sort. So if you want your data in a sorted manner you need to extend some other collection and implement INotifyCollectionChanged. – Adarsha Feb 08 '12 at 03:39
  • 1
    @Adarsha I just extend `ObservableCollection` to include a `Sort` method. I don't create a class that inherits from `ObservableCollection` for that behavior. You can see an example of the sort code in [this answer](http://stackoverflow.com/a/7285548/302677) – Rachel Feb 08 '12 at 03:59
  • note that OP did not extend ObservableCollection, instead he tried to implement INotifyCollectionChanged. Which expects you to implement OnCollectionChanged. Note that ObservableCollection.Move is not available in all versions of .NET e.g. Windows Phone. So to implement Sort, we need to start reinventing the wheel for sorting. Its either use a class implementing IList, INotifyCollectionChanged or use ObservableCollection and reinvet Sorting from the scratch. – Adarsha Feb 09 '12 at 02:46