如何获取XAML中定义的CollectionView

pri*_*tor 8 c# wpf xaml code-behind collectionviewsource

我想绑定到ObservableCollectionXAML中,并在那里应用分组.原则上,这很好.

<UserControl.Resources>
    <CollectionViewSource x:Key="cvs" Source="{Binding Path=TestTemplates}">
        <CollectionViewSource.SortDescriptions>
            <scm:SortDescription PropertyName="Title"/>
        </CollectionViewSource.SortDescriptions>
        <CollectionViewSource.GroupDescriptions>
            <PropertyGroupDescription PropertyName="TestCategory"/>
        </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>
</UserControl.Resources>
Run Code Online (Sandbox Code Playgroud)

然后数据绑定表达式ItemsSource="{Binding Source={StaticResource ResourceKey=cvs}}"代替ItemsSource="{Binding Path=TestTemplates}".

起初,一切看起来都很酷,直到我想从视图模型中刷新UI.问题是,CollectionViewSource.GetDefaultView(TestTemplates)返回的视图与应用分组的XAML中的视图不同.因此,我无法设置选择或做任何有用的事情.

我可以通过将列表再次直接绑定到视图模型的属性并在代码隐藏中设置分组来修复它.但我对这个解决方案并不满意.

private void UserControlLoaded(object sender, RoutedEventArgs e)
{
    IEnumerable source = TemplateList.ItemsSource;
    var cvs = (CollectionView)CollectionViewSource.GetDefaultView(source);
    if (cvs != null)
    {
        cvs.SortDescriptions.Add(new SortDescription("Title", ListSortDirection.Ascending));
        cvs.GroupDescriptions.Add(new PropertyGroupDescription("TestCategory"));
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为,其原因已由John Skeet在此提供.

尽管如此,我希望应该有一种方法来获得正确的观点.我错了吗?

J. *_*non 6

你不能这样做吗?

var _viewSource = this.FindResource("cvs") as CollectionViewSource;
Run Code Online (Sandbox Code Playgroud)

如果数据已连接,我认为将有更新的视图.


Ken*_*art 5

我倾向于只从VM公开集合视图而不是让视图定义它:

public ICollection<Employee> Employees
{
    get { ... }
}

public ICollectionView EmployeesView
{
    get { ... }
}
Run Code Online (Sandbox Code Playgroud)

这样,您的VM就可以完全控制暴露给视图的内容.例如,它可以响应某些用户操作更改排序顺序.


pri*_*tor 2

根据J. Lennon 的回答找到了一种方法。如果我通过命令传递可以访问资源的内容,那么我可以在CollectionViewSource那里查找。

在 XAML 中(CollectionViewResource如上所述):

<Button Command="{Binding Command}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}">Do it!</Button>
Run Code Online (Sandbox Code Playgroud)

在VM代码中:

private void Execute(object parm)
{
    var fe = (FrameworkElement)parm;
    var cvs = (CollectionViewSource)fe.FindResource("cvs");
    cvs.View.Refresh();
}
Run Code Online (Sandbox Code Playgroud)

是提供给RelayCommand 的Execute命令。

这可以回答这个问题,但我不太喜欢它。意见?