首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVVM分页和排序

问MVVM分页和排序
EN

Stack Overflow用户
提问于 2011-03-15 07:34:37
回答 2查看 15.3K关注 0票数 7

我正在努力寻找一个适当的解决方案来实现WPF DataGrid的排序和分页,它符合MVVM P&P。

以下示例说明了一种实现分页的有效方法,它遵循MVVM实践,但排序的自定义实现(一旦实现分页就需要)不遵循MVVM:

http://www.eggheadcafe.com/tutorials/aspnet/8a2ea78b-f1e3-45b4-93ef-32b2d802ae17/wpf-datagrid-custom-pagin.aspx

我目前有一个绑定到CollectionViewSource的DataGrid (使用GroupDescriptions和SortDescritptions在XAML中定义)绑定到我的ViewModel中的ObservableCollection。一旦您通过限制DataGrid每页获得的项目数量来实现分页,它就会打破CollectionViewSource中定义的排序,因为它只对项目的子集进行排序。在MVVM下实现分页和排序的最佳方法是什么?

谢谢,

Aaron

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-03-15 08:47:55

前几天我写了一个PagingController类来帮助分页,所以你可以这样做了:

你将不得不清理一些源代码,因为他们使用了一些MS代码合同,他们引用了一些(真正基础的)来自Prism的实用工具,等等。

代码使用示例( ViewModel.cs**):** -

代码语言:javascript
复制
private const int PageSize = 20;

private static readonly SortDescription DefaultSortOrder = new SortDescription("Id", ListSortDirection.Ascending);

private readonly ObservableCollection<Reservation> reservations = new ObservableCollection<Reservation>();

private readonly CollectionViewSource reservationsViewSource = new CollectionViewSource();

public ViewModel()
{
    this.reservationsViewSource.Source = this.reservations;

    var sortDescriptions = (INotifyCollectionChanged)this.reservationsViewSource.View.SortDescriptions;
    sortDescriptions.CollectionChanged += this.OnSortOrderChanged;

    // The 5000 here is the total number of reservations
    this.Pager = new PagingController(5000, PageSize);
    this.Pager.CurrentPageChanged += (s, e) => this.UpdateData();

    this.UpdateData();

}

public PagingController Pager { get; private set; }

public ICollectionView Reservations
{
    get { return this.reservationsViewSource.View; }
}

private void UpdateData()
{
    var currentSort = this.reservationsViewSource.View.SortDescriptions.DefaultIfEmpty(DefaultSortOrder).ToArray();

    // This is the "fetch the data" method, the implementation of which
    // does not directly interest us for this example.
    var data = this.crsService.GetReservations(this.Pager.CurrentPageStartIndex, this.Pager.PageSize, currentSort);
    this.reservations.Clear();
    this.reservations.AddRange(data);
}

private void OnSortOrderChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add) {
        this.UpdateData();
    }
}

XAML用法示例(XAML - View.xaml**):**

代码语言:javascript
复制
<DataGrid ... ItemSource="{Binding Reservations}" />

<!-- all the rest is UI to interact with the pager -->
<StackPanel>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="4">
        <StackPanel.Resources>
            <Style TargetType="{x:Type Button}">
                <Setter Property="FontFamily" Value="Webdings" />
                <Setter Property="Width" Value="60" />
                <Setter Property="Margin" Value="4,0,4,0" />
            </Style>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="Margin" Value="4,0,4,0" />
                <Setter Property="VerticalAlignment" Value="Center" />
            </Style>
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="Margin" Value="4,0,4,0" />
                <Setter Property="Width" Value="40" />
            </Style>
        </StackPanel.Resources>
        <Button Content="9" Command="{Binding Path=Pager.GotoFirstPageCommand}" />
        <Button Content="3" Command="{Binding Path=Pager.GotoPreviousPageCommand}" />
        <TextBlock Text="Page" />
        <TextBox Text="{Binding Path=Pager.CurrentPage, ValidatesOnExceptions=True}" />
        <TextBlock Text="{Binding Path=Pager.PageCount, StringFormat=of {0}}" />
        <Button Content="4" Command="{Binding Path=Pager.GotoNextPageCommand}" />
        <Button Content=":" Command="{Binding Path=Pager.GotoLastPageCommand}" />
    </StackPanel>
    <ScrollBar Orientation="Horizontal" Minimum="1" Maximum="{Binding Path=Pager.PageCount}" Value="{Binding Path=Pager.CurrentPage}"/>
</StackPanel>

简短说明:

正如您所看到的,ViewModel实际上并不能做太多事情。它保留一个表示当前页面的项的集合,并向视图公开一个CollectionView (用于数据绑定)和一个PagingController。然后,它所做的就是在每次PagingController指示某些内容发生更改时更新集合中的数据项(以及CollectionView中的数据项)。当然,这意味着您需要一个方法,在给定起始索引和页面大小的情况下,SortDescription[]将返回这些参数所描述的数据片。这是您的业务逻辑的一部分,我在这里没有包含它的代码。

在Xaml端,所有工作都是通过绑定到PagingController来完成的。我在这里展示了全部功能(绑定到First/Prev/Next/Last命令的按钮,直接绑定TextBox到CurrentPage的按钮,以及绑定ScrollBar到CurrentPage的按钮)。通常情况下,您不会同时使用所有这些。

票数 16
EN

Stack Overflow用户

发布于 2011-03-15 07:42:19

您应该在ViewModel中使用ListCollectionView类型的集合属性,并将网格绑定到它。这样,CollectionView定义就不会位于视图中,而是位于ViewModel中(它所属的位置),这将帮助您轻松地在ViewModel中执行所有操作(分页、排序或过滤)。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5305883

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档