我有一个ViewModel,其中包含两个ICollectionView,它们作为ItemsSource绑定到两个不同的ListBox。两个ListBox都使用不同的过滤器来封装相同的ObservableCollection。最初一切正常,两个ListBox都填充正确。
但是,当我更改ObservableCollection中的项并修改与过滤相关的属性时,ListBoxes不会更新。在调试器中,我发现两个ICollectionView的SourceCollection为空,虽然我的ObservableCollection仍然存在。
这是我如何修改项目以确保更新ICollectionViews,方法是删除并添加相同的项目:
这个机制在我使用相同类别的另一个上下文中也有效。
此外,我发现如果在ICollectionViews的CollectionChanged事件上注册侦听器,则问题会消失。 我确保从GUI线程创建和修改它们,并怀疑垃圾回收是问题所在,但目前我卡住了...有什么想法吗?
更新:
在调试时,我意识到在将我的UserControl托管到其中的WinForms表单上调用ShowDialog()之前,SourceCollections仍然存在。 当显示对话框时,它们消失了。
我像这样创建ICollectionViews:
但是,当我更改ObservableCollection中的项并修改与过滤相关的属性时,ListBoxes不会更新。在调试器中,我发现两个ICollectionView的SourceCollection为空,虽然我的ObservableCollection仍然存在。
这是我如何修改项目以确保更新ICollectionViews,方法是删除并添加相同的项目:
private void UnassignTag(TagViewModel tag)
{
TrackChangedTagOnCollectionViews(tag, t => t.IsAssigned = false);
}
private void TrackChangedTagOnCollectionViews(TagViewModel tag, Action<TagViewModel> changeTagAction)
{
_tags.Remove(tag);
changeTagAction.Invoke(tag);
_tags.Add(tag);
}
这个机制在我使用相同类别的另一个上下文中也有效。
此外,我发现如果在ICollectionViews的CollectionChanged事件上注册侦听器,则问题会消失。 我确保从GUI线程创建和修改它们,并怀疑垃圾回收是问题所在,但目前我卡住了...有什么想法吗?
更新:
在调试时,我意识到在将我的UserControl托管到其中的WinForms表单上调用ShowDialog()之前,SourceCollections仍然存在。 当显示对话框时,它们消失了。
我像这样创建ICollectionViews:
AvailableTags = new CollectionViewSource { Source = _tags }.View;
AssignedTags = new CollectionViewSource { Source = _tags }.View;
这是我如何绑定其中一个(另一个也很相似)的方法:
<ListBox Grid.Column="0" ItemsSource="{Binding AvailableTags}" Style="{StaticResource ListBoxStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Style="{StaticResource ListBoxItemBorderStyle}">
<DockPanel>
<Button DockPanel.Dock="Right" ToolTip="Assign" Style="{StaticResource IconButtonStyle}"
Command="{Binding Path=DataContext.AssignSelectedTagCommand, RelativeSource={RelativeSource AncestorType={x:Type tags:TagsListView}}}"
CommandParameter="{Binding}">
<Image Source="..."/>
</Button>
<TextBlock Text="{Binding Name}" Style="{StaticResource TagNameTextBlockStyle}"/>
</DockPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我在我的ViewModel中使用MvvmLight的RelayCommand<T>
作为ICommand
的实现:
AssignSelectedTagCommand = new RelayCommand<TagViewModel>(AssignTag);