我有以下测试代码:
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集合。该集合将在添加/更改/删除时通知我正在尝试将这些事件转换为WPF的INotify
事件。
希望这很清楚(已经很晚了)。
答案 0 :(得分:0)
ObservableCollection<T>
也实现了INotifyPropertyChanged
。由于您的收集只是IEnumerable<T>
,因此您没有任何属性可以为其创建事件,但ObservableCollection<T>
为PropertyChanged
和Count
属性创建Item[]
个事件。您可以尝试通过派生ObservableCollection<T>
并实施IList<T>
来使您的收藏更像INotifyPropertyChanged
。不过,我不知道这是否能解决你的问题。
答案 1 :(得分:0)
我不明白为什么我一直看到人们试图在WPF中实现自己的集合。只需使用ObservableCollection<SomeItem>
即可完成所有CollectionChanged通知。
private ObservableCollection<SomeItem> collection =
new ObservableCollection<SomeItem>();
如果您想在SomeItem.PropertyChanged
上发生某些事情,请SomeItem
实施INotifyPropertyChanged
至于为什么没有引发CollectionChanged,你设置 ItemsSource属性,而不是绑定它。设置它意味着您正在复制collection
并将其存储在ListBox.ItemsSource
中。绑定它意味着您会告诉ListBox.ItemsSource
引用collection
来获取数据。