ICollectionView的SourceCollection为null

Eag*_*eak 6 c# wpf

我有一个带有两个ICollectionViews 的ViewModel,它们被绑定为ItemsSource两个不同的ListBoxes.两者都包装相同ObservableCollection,但使用不同的过滤器.最初一切正常,两个ListBox都正确填充.

但是,当我更改ObservableCollection中的项并修改与过滤相关的属性时,ListBoxes不会更新.在调试器中,我发现两个ICollectionVIews的SourceCollection都为null,尽管我的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);
}
Run Code Online (Sandbox Code Playgroud)

该机制适用于我使用相同类的另一个上下文.

此外,我意识到如果我在ICollectionViews的CollectionChanged事件上注册监听器,问题就会消失.我确保从GUI线程创建和修改它们并怀疑垃圾收集是问题所在,但目前我被卡住了......想法?

更新:

在调试时我意识到在我调用ShowDialog()托管UserControl的WinForms表单之前,SourceCollections仍然存在.显示对话框后,它们就消失了.

我像这样创建ICollectionViews:

AvailableTags = new CollectionViewSource { Source = _tags }.View;
AssignedTags = new CollectionViewSource { Source = _tags }.View;
Run Code Online (Sandbox Code Playgroud)

这是我如何绑定其中一个(另一个非常相似):

<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>
Run Code Online (Sandbox Code Playgroud)

我在我的ViewModel中使用MvvmLight RelayCommand<T>作为ICommand实现:

AssignSelectedTagCommand = new RelayCommand<TagViewModel>(AssignTag);
Run Code Online (Sandbox Code Playgroud)

sco*_*zey 12

我也有这个问题,有类似的用例.当我更新底层集合时,我会调用Refresh()所有过滤后的视图.有时,这会导致NullReferenceException从内部抛出ListCollectionView.PrepareLocalArray()因为SourceCollection为null.

问题是你不应该绑定到属性CollectionView,而是CollectionViewSource.View属性.

我是这样做的:

public class ViewModel {

    // ...

    public ViewModel(ObservableCollection<ItemViewModel> items)
    {
        _source = new CollectionViewSource()
        {
            Source = items,
            IsLiveFilteringRequested = true,
            LiveFilteringProperties = { "FilterProperty" }
        };

        _source.Filter += (src, args) =>
        {
            args.Accepted = ((ItemViewModel) args.Item).FilterProperty == FilterField;
        };
    }

    // ...

    public ICollectionView View
    {
        get { return _source.View; }
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • 宇宙受到我们自己理解的限制.;)我认为发生的事情是,在引擎盖下,`.View`属性引用的对象发生了变异,而`.View`属性本身也发生了变化.我不确定它是如何与WPF数据绑定交互的,但如果你执行`.View.Refresh()`它肯定会影响你.无论如何.很高兴我能帮你解决问题. (3认同)
  • 这不完全一样.`CollectionViewSource.View`是一个属性,值会改变. (2认同)

Chr*_*ell 7

您遇到的问题的原因CollectionViewSource是正在收集垃圾。