У меня есть следующий тестовый код:
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;
}
и 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>
внешний список заполняется при загрузке. когда расширитель расширяется, я затем устанавливаю свойство ItemsSource
внутреннего списка (причина, по которой я слышу это вместо использования привязки, заключается в том, что эта операция довольно медленная, и я хочу, чтобы она выполнялась только в том случае, если использование решит просмотреть элементы). Внутренний список отображается нормально, но на самом деле он не подписывается на событие CollectionChanged
в коллекции. Я пробовал это с ICollection
вместо IEnumerable
и добавлял INotifyPropertyChanged
, а также заменял INotifyCollectionChanged
на INotifyPropertyChanged
. Единственный способ заставить это работать — выпотрошить мой класс SomeCollection
и наследовать от ObservableCollection<SomeItem>
. Причина, по которой я пытаюсь использовать свою собственную роль INotifyCollectionChanged
вместо использования ObservableCollection
, заключается в том, что я оборачиваю коллекцию COM в реальный код. Эта коллекция будет уведомлять о добавлении/изменении/удалении, и я пытаюсь преобразовать их в события INotify
для WPF.
Надеюсь, это достаточно ясно (уже поздно).
INotifyCollectionChanged
и вообще не реализуетеINotifyPropertyChanged
. Вероятно, не стоит исследовать, чтобы найти конкретные причины, поскольку вам лучше просто изменитьSomeCollection
, чтобы он наследовал отObservableCollection<T>
, и многое сделать за вас. Зачем изобретать велосипед? Вы по-прежнему сможете переопределять методы, чтобы настроить его поведение, если вам нужно. - person Sean Hanley   schedule 30.12.2011