ICollectionView的SourceCollection为null [英] ICollectionView's SourceCollection is null

查看:44
本文介绍了ICollectionView的SourceCollection为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有两个 ICollectionView 的ViewModel,它们作为 ItemsSource s绑定到两个不同的 ListBox es.两者都包装相同的 ObservableCollection ,但具有不同的过滤器.最初一切正常,并且两个ListBox都显示正确填充.

I have a ViewModel with two ICollectionViews which are bound as ItemsSources to two different ListBoxes. Both wrap the same ObservableCollection, but with different filters. Everything works fine initially and both ListBoxes appear properly filled.

但是,当我更改ObservableCollection中的一项并修改与过滤相关的属性时,ListBoxes不会更新.在调试器中,我发现两个ICollectionVIews的SourceCollection为null,尽管我的ObservableCollection仍然存在.

However when I change an item in the ObservableCollection and modify a property which is relevant for filtering, the ListBoxes don't get updated. In the debugger I found that SourceCollection for both ICollectionVIews is null although my ObservableCollection is still there.

这是我修改项目的方式,以确保通过删除和添加相同的项目来更新ICollectionView:

This is how I modify an item making sure that the ICollectionViews are updated by removing and adding the same item:

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);
}

该机制在另一个使用相同类的上下文中起作用.

The mechanism works in another context where I use the same class.

我还意识到,如果我在ICollectionViews的CollectionChanged事件上注册侦听器,问题将消失.我确定我是从GUI线程创建和修改它们的,并且怀疑是否存在垃圾回收问题,但是目前我陷入了困境……想法?

Also I realized that the problem disappears if I register listeners on the ICollectionViews' CollectionChanged events. I made sure that I create and modify them from the GUI thread and suspect that garbage collection is the problem, but currently I'm stuck... Ideas?

更新:

在调试时,我意识到在我的UserControl所在的WinForms窗体上调用 ShowDialog()之前,SourceCollections仍然存在.显示对话框后,它们消失了.

While debugging I realized that the SourceCollections are still there right before I call ShowDialog() on the WinForms Form in which my UserControl is hosted. When the dialog is shown they're gone.

我这样创建ICollectionViews:

I create the ICollectionViews like this:

AvailableTags = new CollectionViewSource { Source = _tags }.View;
AssignedTags = new CollectionViewSource { Source = _tags }.View;

这是我绑定两者之一的方式(另一个非常相似):

Here's how I bind one of the two (the other one is pretty similar):

<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 实现:

I use MvvmLight's RelayCommand<T> as ICommand implementation in my ViewModel:

AssignSelectedTagCommand = new RelayCommand<TagViewModel>(AssignTag);

推荐答案

在类似的用例中,我也遇到了这个问题.更新基础集合时,我将在所有过滤的视图上调用 Refresh().有时,这会导致从 ListCollectionView.PrepareLocalArray()内部抛出 NullReferenceException ,因为 SourceCollection 为null.

I had this issue too, with a similar use-case. When I updated the underlying collection, I would call Refresh() on all the filtered views. Sometimes, this would result in a NullReferenceException thrown from within ListCollectionView.PrepareLocalArray() because SourceCollection is null.

问题在于您不应该绑定到 CollectionView ,而应该绑定到 CollectionViewSource.View 属性.

The problem is that you shouldn't be binding to the CollectionView, but to the CollectionViewSource.View property.

这是我的操作方式:

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; }
    }

    // ...
}

这篇关于ICollectionView的SourceCollection为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆