为什么 DataPager 没有获取我的 TotalItemCount?

发布于 2024-10-15 07:31:28 字数 4433 浏览 5 评论 0原文

我正在尝试创建一个 MVVM 友好的页面,其中包含一个数据网格和一个用于 Silverlight 的数据分页器。在我的视图模型上,我实现了 IPgedCollectionView 接口

public class DiscountViewModel : INotifyPropertyChanged, IPagedCollectionView

,并且实现了获取 ItemCount 和 TotalItemCount 所需的所有方法。

public bool CanChangePage {
        get { return TotalItemCount > PageIndex * PageSize; }
    }

    public bool IsPageChanging {
        get { return false; }
    }

    public int ItemCount {
        get { return itemCount; }
        set { itemCount = value; RaisePropertyChange("ItemCount"); }
    }

   public bool MoveToFirstPage() {
        PageChanging(this, new PageChangingEventArgs(PageIndex));
        PageIndex = 0;
        PageChanged(this, null);
        return true;
    }

    public bool MoveToLastPage() {
        throw new NotImplementedException();
    }

    public bool MoveToNextPage() {
        PageChanging(this, new PageChangingEventArgs(PageIndex));
        PageIndex++;
        PageChanged(this, null);
        return true;
    }

    public bool MoveToPage(int pageIndex) {
        PageChanging(this, new PageChangingEventArgs(PageIndex));
        PageIndex = pageIndex;
        PageChanged(this, null);
        return true;
    }

    public bool MoveToPreviousPage() {
        PageChanging(this, new PageChangingEventArgs(PageIndex));
        PageIndex--;
        PageChanged(this, null);
        return true;
    }

    public event EventHandler<EventArgs> PageChanged;

    public event EventHandler<PageChangingEventArgs> PageChanging;

    public int PageIndex {
        get { return pageIndex; }
        set { pageIndex = value; RaisePropertyChange("PageIndex"); }
    }

    public int PageSize {
        get { return pageSize; }
        set { pageSize = value; RaisePropertyChange("PageSize"); }
    }

    public int TotalItemCount {
        get { return totalItemCount; }
        set { totalItemCount = value; RaisePropertyChange("TotalItemCount"); }
    }

XAML 工作正常,可以绑定到项目,并且数据网格在最初加载时显示前五个项目。

<data:DataGrid x:Name="discountsDataGrid"  ItemsSource="{Binding Discounts, Mode=TwoWay}"  MinHeight="200" AutoGenerateColumns="False" SelectedItem="{Binding SelectedDiscount, Mode=TwoWay}">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="RowEditEnded">
                            <i:InvokeCommandAction Command="{Binding SaveChangesCommand}" CommandParameter="{Binding SelectedDiscount}"  />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>

                    <data:DataGrid.Columns>
                        <data:DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                        <data:DataGridTextColumn Header="Discount Amount" Binding="{Binding Amount}" />
                    </data:DataGrid.Columns>
                </data:DataGrid>
                <sdk:DataPager  PageSize="{Binding PageSize}"  Source="{Binding Path=ItemsSource, ElementName=discountsDataGrid}" Margin="0,-1,0,0" />

用于获取折扣然后设置总计数的相关代码全部执行,并且数字达到了我的预期(返回的项目为 5,所有折扣的总数为 9)

public void LoadDiscounts(Object parameter){
        EntityQuery<Discount> eq = ctx.GetPagedDiscountsQuery(PageIndex, PageSize, "");
        eq.IncludeTotalCount = true;
        ctx.Load<Discount>(eq, OnDiscountsLoaded, null);
    }

    private void OnDiscountsLoaded(LoadOperation<Discount> loadOperation) {
        if (loadOperation.Error != null) {

        } else {
            Discounts = loadOperation.Entities;   
            ItemCount = loadOperation.TotalEntityCount;
            ctx.GetDiscountCount(OnCountCompleted, null);
            RaisePropertyChange("Discounts");
        }
    }

    private void OnCountCompleted(InvokeOperation<int> op) {
        TotalItemCount = op.Value;
        RaisePropertyChange("Discounts");
        RaisePropertyChange("TotalItemCount");
    }

但数据分页器似乎没有发现还有5折以上。我可以看到 TotalItemCount 设置正确。奇怪的是,除了设置值之外,TotalItemCount 属性永远不会被任何其他代码调用。数据分页器不应该使用它来确定是否可以单击上一个/下一个/第一个/最后一个按钮吗?

更新 因此,我在订阅 MouseEnter 事件时查看了 DataPager,发现了一些有趣的东西。 ItemCount 是 5,无论我在 ViewModel 上将其设置为什么(例如,手动将其设置为 9),DataPager 只会查看其集合中的项目来确定实际有多少项目。它不是从 ViewModel 类中读取这些值。我想我读到如果周围的上下文实现了 IPgedCollectionView,则 DataPager 将使用这些方法来确定大小/页面/等。

I'm trying to create an MVVM-friendly page that contains a datagrid and a data pager for Silverlight. On my viewmodel, I've implemented the IPagedCollectionView interface

public class DiscountViewModel : INotifyPropertyChanged, IPagedCollectionView

and I've implemented all the methods necessary to get ItemCount and TotalItemCount.

public bool CanChangePage {
        get { return TotalItemCount > PageIndex * PageSize; }
    }

    public bool IsPageChanging {
        get { return false; }
    }

    public int ItemCount {
        get { return itemCount; }
        set { itemCount = value; RaisePropertyChange("ItemCount"); }
    }

   public bool MoveToFirstPage() {
        PageChanging(this, new PageChangingEventArgs(PageIndex));
        PageIndex = 0;
        PageChanged(this, null);
        return true;
    }

    public bool MoveToLastPage() {
        throw new NotImplementedException();
    }

    public bool MoveToNextPage() {
        PageChanging(this, new PageChangingEventArgs(PageIndex));
        PageIndex++;
        PageChanged(this, null);
        return true;
    }

    public bool MoveToPage(int pageIndex) {
        PageChanging(this, new PageChangingEventArgs(PageIndex));
        PageIndex = pageIndex;
        PageChanged(this, null);
        return true;
    }

    public bool MoveToPreviousPage() {
        PageChanging(this, new PageChangingEventArgs(PageIndex));
        PageIndex--;
        PageChanged(this, null);
        return true;
    }

    public event EventHandler<EventArgs> PageChanged;

    public event EventHandler<PageChangingEventArgs> PageChanging;

    public int PageIndex {
        get { return pageIndex; }
        set { pageIndex = value; RaisePropertyChange("PageIndex"); }
    }

    public int PageSize {
        get { return pageSize; }
        set { pageSize = value; RaisePropertyChange("PageSize"); }
    }

    public int TotalItemCount {
        get { return totalItemCount; }
        set { totalItemCount = value; RaisePropertyChange("TotalItemCount"); }
    }

The XAML is working fine to bind to the items and the datagrid shows the first five items when initially loaded.

<data:DataGrid x:Name="discountsDataGrid"  ItemsSource="{Binding Discounts, Mode=TwoWay}"  MinHeight="200" AutoGenerateColumns="False" SelectedItem="{Binding SelectedDiscount, Mode=TwoWay}">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="RowEditEnded">
                            <i:InvokeCommandAction Command="{Binding SaveChangesCommand}" CommandParameter="{Binding SelectedDiscount}"  />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>

                    <data:DataGrid.Columns>
                        <data:DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                        <data:DataGridTextColumn Header="Discount Amount" Binding="{Binding Amount}" />
                    </data:DataGrid.Columns>
                </data:DataGrid>
                <sdk:DataPager  PageSize="{Binding PageSize}"  Source="{Binding Path=ItemsSource, ElementName=discountsDataGrid}" Margin="0,-1,0,0" />

The relavent code for getting the discounts and then setting the total count all execute and the numbers come out to what I'd expect (5 for the items returned and 9 for the total count of all discounts)

public void LoadDiscounts(Object parameter){
        EntityQuery<Discount> eq = ctx.GetPagedDiscountsQuery(PageIndex, PageSize, "");
        eq.IncludeTotalCount = true;
        ctx.Load<Discount>(eq, OnDiscountsLoaded, null);
    }

    private void OnDiscountsLoaded(LoadOperation<Discount> loadOperation) {
        if (loadOperation.Error != null) {

        } else {
            Discounts = loadOperation.Entities;   
            ItemCount = loadOperation.TotalEntityCount;
            ctx.GetDiscountCount(OnCountCompleted, null);
            RaisePropertyChange("Discounts");
        }
    }

    private void OnCountCompleted(InvokeOperation<int> op) {
        TotalItemCount = op.Value;
        RaisePropertyChange("Discounts");
        RaisePropertyChange("TotalItemCount");
    }

But the datapager doesn't seem to pick up that there are more than 5 discounts. I can see that the TotalItemCount is correctly set. The odd thing about this, is that the TotalItemCount property is never called by any other code except to set the value. Shouldn't the datapager be using that to determine whether the Prev / Next / First / Last buttons can be clicked?

Update
So I looked at the DataPager while subscribing to the MouseEnter event and found something interesting. The ItemCount is 5 and no matter what I set it to on the ViewModel (for instance, setting it to 9 manually), the DataPager only looks at the items in its collection to determine how many items there actually are. It is not reading those values from the ViewModel class. I thought I read that if the surrounding context implements IPagedCollectionView, that the DataPager would use those methods to determine size / page /etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吹泡泡o 2024-10-22 07:31:28

DataPager 控件的 Source 属性应绑定到集合。不是 DataGrid 控件的 ItemsSource 属性。

来自 DataPager。源属性

源可以是任何 IEnumerable
收藏。当绑定到
未实现的 IEnumerable
IPgedCollectionView,数据分页器
表现得好像所有数据都在
单页。设置数据分页器
属性不会有任何影响
控制。

通常,源是一个集合
实现 IPgedCollectionView。
IPgedCollectionView 提供
分页功能,以及
DataPager控件为用户提供了
与交互的接口
IPgedCollectionView。提供
寻呼功能
IEnumerable集合,可以换行
它在 PagedCollectionView 类中。

List<String> itemList = new List<String>();
// Generate some items to add to the list.
for (int i = 1; i <= 33; i++)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder("Item ");
    sb.Append(i.ToString());
    itemList.Add(sb.ToString());
}
// Wrap the itemList in a PagedCollectionView for paging functionality
PagedCollectionView itemListView = new PagedCollectionView(itemList);

// Set the DataPager and ListBox to the same data source.
dataPager1.Source = itemListView;
listBox1.ItemsSource = itemListView;

The DataPager controls Source property should be bound to the collection. Not the DataGrid control's ItemsSource property.

From DataPager.Source property:

The source can be any IEnumerable
collection. When bound to an
IEnumerable that does not implement
IPagedCollectionView, the DataPager
behaves as if all the data is on a
single page. Setting DataPager
properties will not have any effect on
the control.

Typically, the source is a collection
that implements IPagedCollectionView.
The IPagedCollectionView provides
paging functionality, and the
DataPager control provides a user
interface for interacting with the
IPagedCollectionView. To provide
paging functionality for an
IEnumerable collection, you can wrap
it in the PagedCollectionView class.

List<String> itemList = new List<String>();
// Generate some items to add to the list.
for (int i = 1; i <= 33; i++)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder("Item ");
    sb.Append(i.ToString());
    itemList.Add(sb.ToString());
}
// Wrap the itemList in a PagedCollectionView for paging functionality
PagedCollectionView itemListView = new PagedCollectionView(itemList);

// Set the DataPager and ListBox to the same data source.
dataPager1.Source = itemListView;
listBox1.ItemsSource = itemListView;
只等公子 2024-10-22 07:31:28

我注意到您正在使用 WCF RIA 服务。在更简单的场景中,您可以简单地将 DataGrid 和 DataPager 绑定到 DomainDataSource,而无需实现任何内容。但我猜你有一个更复杂的要求,这就是为什么你要手工完成所有事情。

I have noticed that you are using WCF RIA Services. In simpler scenarios you can simply bind both your DataGrid and DataPager to a DomainDataSource and you will not have to implement anything. But I guess that you had a more complex requirement and that is why you are doing everything by hand.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文