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.
The DataPager controls
Source
property should be bound to the collection. Not the DataGrid control'sItemsSource
property.From DataPager.Source property: