为什么 DataPager 没有获取我的 TotalItemCount?
我正在尝试创建一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
DataPager 控件的
Source
属性应绑定到集合。不是 DataGrid 控件的ItemsSource
属性。来自 DataPager。源属性:
The DataPager controls
Source
property should be bound to the collection. Not the DataGrid control'sItemsSource
property.From DataPager.Source property:
我注意到您正在使用 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.