1. Diff
1.1
ObservableCollection ObservableCollection继承了Collection,INotifyCollectionChanged,INotifyPropertyChanged
-
Collection:为泛型集合提供基类
-
INotifyCollectionChanged:将集合的动态更改通知给侦听器,例:何时添加或移除项或者重置整个集合对象。
-
INotifyPropertyChanged:向客户端发出某一属性值已经更改的通知
注意:ObservableCollection表示一个动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知。满足MVVM模式。
1.2 List
List继承了IList,ICollection,IEnumerable,IList,ICollection,IEnumerable
-
IList:表示可按照索引单独访问的一组对象
-
ICollection:定义操作泛型集合的方法
-
IEnmerable:公开枚举器,改枚举器支持在指定类型的集合上进行简单迭代
-
IList:表示可按照索引单独访问的对象的非泛型集合
-
ICollection:定义所有非泛型集合的大小、枚举器和同步方法
-
IEnumerable:公开枚举器,该枚举器支持在非泛型集合上进行简单迭代
List表示可通过索引访问的对象的强类型列表。提供用于对列表进行搜索、排序和操作的方法。
2. Create Pager View
先創建一個UserController,名字為Pager,如下是xaml和xaml.cs
<UserControl x:Class="xxxxx.Views.Control.Pager"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:xxxxx.Views.Control"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d">
<UserControl.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignRaisedLightButton}">
<Setter Property="Width" Value="35"/>
<Setter Property="Height" Value="30"/>
</Style>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2.5*" />
</Grid.ColumnDefinitions>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<TextBlock Text="每页显示" VerticalAlignment="Center" FontWeight="Bold" Margin="4"/>
<ComboBox Width="45"
Height="30"
FontSize="15"
FontWeight="Bold"
Foreground="BlueViolet"
SelectedIndex="{Binding ComboBoxIndex, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource MaterialDesignComboBox}">
<ComboBoxItem Content="20" />
<ComboBoxItem Content="50" />
<ComboBoxItem Content="100" />
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ComboBoxSelectChange}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
<TextBlock Text="条" VerticalAlignment="Center" FontWeight="Bold" Margin="4"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<Button x:Name="FirstPageButton" Margin="10" Click="FirstPageButton_Click" Style="{StaticResource MaterialDesignRaisedLightButton}">
<materialDesign:PackIcon Kind="ArrowCollapseLeft" Height="20" Width="20"/>
</Button>
<Button x:Name="PreviousPageButton" Margin="10" Click="PreviousPageButton_Click" Style="{StaticResource MaterialDesignRaisedLightButton}">
<materialDesign:PackIcon Kind="ArrowLeft" Height="20" Width="20"/>
</Button>
<TextBlock VerticalAlignment="Center" FontWeight="Bold">
<Run Text="第"/>
<Run x:Name="rCurrent" Text="0"/>
<Run Text="页"/>
</TextBlock>
<Button Margin="10" x:Name="NextPageButton" Click="NextPageButton_Click" Style="{StaticResource MaterialDesignRaisedLightButton}">
<materialDesign:PackIcon Kind="ArrowRight" Height="20" Width="20"/>
</Button>
<Button Margin="10" x:Name="LastPageButton" Click="LastPageButton_Click" Style="{StaticResource MaterialDesignRaisedLightButton}">
<materialDesign:PackIcon Kind="ArrowCollapseRight" Height="20" Width="20"/>
</Button>
<TextBlock VerticalAlignment="Center" FontWeight="Bold">
<Run Text="共"/>
<Run x:Name="rTotal" Text="0"/>
<Run Text="页"/>
</TextBlock>
</StackPanel>
</Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace xxxxx.Views.Control
{
/// <summary>
/// Pager.xaml 的互動邏輯
/// </summary>
public partial class Pager : UserControl
{
public static RoutedEvent FirstPageEvent;
public static RoutedEvent PreviousPageEvent;
public static RoutedEvent NextPageEvent;
public static RoutedEvent LastPageEvent;
public static readonly DependencyProperty CurrentPageProperty;
public static readonly DependencyProperty TotalPageProperty;
public string CurrentPage
{
get { return (string)GetValue(CurrentPageProperty); }
set { SetValue(CurrentPageProperty, value); }
}
public string TotalPage
{
get { return (string)GetValue(TotalPageProperty); }
set { SetValue(TotalPageProperty, value); }
}
public Pager()
{
InitializeComponent();
}
static Pager()
{
FirstPageEvent = EventManager.RegisterRoutedEvent("FirstPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
PreviousPageEvent = EventManager.RegisterRoutedEvent("PreviousPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
NextPageEvent = EventManager.RegisterRoutedEvent("NextPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
LastPageEvent = EventManager.RegisterRoutedEvent("LastPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
CurrentPageProperty = DependencyProperty.Register("CurrentPage", typeof(string), typeof(Pager), new PropertyMetadata(string.Empty,new PropertyChangedCallback(OnCurrentPageChanged)));
TotalPageProperty = DependencyProperty.Register("TotalPage", typeof(string), typeof(Pager), new PropertyMetadata(string.Empty,new PropertyChangedCallback(OnTotalPageChanged)));
}
public event RoutedEventHandler FirstPage
{
add { AddHandler(FirstPageEvent, value); }
remove { RemoveHandler(FirstPageEvent, value); }
}
public event RoutedEventHandler PreviousPage
{
add { AddHandler(PreviousPageEvent, value); }
remove { RemoveHandler(PreviousPageEvent, value); }
}
public event RoutedEventHandler NextPage
{
add { AddHandler(NextPageEvent, value); }
remove { RemoveHandler(NextPageEvent, value); }
}
public event RoutedEventHandler LastPage
{
add { AddHandler(LastPageEvent, value); }
remove { RemoveHandler(LastPageEvent, value); }
}
public static void OnTotalPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Pager p = d as Pager;
if(p != null)
{
Run rTotal = (Run)p.FindName("rTotal");
rTotal.Text = (string)e.NewValue;
}
}
private static void OnCurrentPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Pager p = d as Pager;
if(p != null)
{
Run rCurrrent = (Run)p.FindName("rCurrent");
rCurrrent.Text = (string)e.NewValue;
}
}
private void FirstPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(FirstPageEvent, this));
}
private void PreviousPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(PreviousPageEvent, this));
}
private void NextPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(NextPageEvent, this));
}
private void LastPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(LastPageEvent, this));
}
}
}
3.Create PageList View/ViewModel
PageListView中引入前面的Pager
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<DataGrid ItemsSource="{Binding ResultFakeSource,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="False"
CanUserAddRows="False"
Margin="10"
Height="500">
<DataGrid.Columns>
<DataGridTextColumn Header="Item Id" Binding="{Binding ItemId}" Width="80"/>
<DataGridTextColumn Header="Item Name" Binding="{Binding ItemName}" Width="180"/>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
<local:Pager TotalPage="{Binding TotalPage}"
CurrentPage="{Binding CurrentPage, Mode=TwoWay}"
HorizontalAlignment="Center"
Margin="0,20,0,0"
Grid.Row="1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="FirstPage">
<i:InvokeCommandAction Command="{Binding FirstPageCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviousPage">
<i:InvokeCommandAction Command="{Binding PreviousPageCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="NextPage">
<i:InvokeCommandAction Command="{Binding NextPageCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="LastPage">
<i:InvokeCommandAction Command="{Binding LastPageCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</local:Pager>
</Grid>
using ImTools;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace xxxxx.ViewModels.LeftViewModel
{
public class PageListViewModel : BindableBase
{
private readonly IEventAggregator aggregator;
#region Command
public DelegateCommand FirstPageCommand { get; set; }
public DelegateCommand PreviousPageCommand { get; set; }
public DelegateCommand NextPageCommand { get; set; }
public DelegateCommand LastPageCommand { get; set; }
public DelegateCommand ComboBoxSelectChange { get; set; }
#endregion
#region Parameter
private int totalPage;
public int TotalPage
{
get { return totalPage; }
set { totalPage = value; RaisePropertyChanged(); }
}
private int currentPage;
public int CurrentPage
{
get { return currentPage; }
set { currentPage = value; RaisePropertyChanged(); }
}
private int pageSize;
public int PageSize
{
get { return pageSize; }
set { pageSize = value; RaisePropertyChanged(); }
}
private int comboBoxIndex = 0;
public int ComboBoxIndex
{
get { return comboBoxIndex; }
set { comboBoxIndex = value; RaisePropertyChanged(); }
}
private ObservableCollection<FakeDatabase> fakeSource;
public ObservableCollection<FakeDatabase> FakeSource
{
get { return fakeSource; }
set { fakeSource = value; RaisePropertyChanged(); }
}
private ObservableCollection<FakeDatabase> resultFakeSource;
public ObservableCollection<FakeDatabase> ResultFakeSource
{
get { return resultFakeSource; }
set { resultFakeSource = value; RaisePropertyChanged(); }
}
#endregion
public PageListViewModel(IEventAggregator aggregator)
{
this.aggregator = aggregator;
FakeSource = new ObservableCollection<FakeDatabase>();
ResultFakeSource = new ObservableCollection<FakeDatabase>();
InitialLoad();
ComboBoxSelectAction();
FirstPageCommand = new DelegateCommand(FirstPageAction);
PreviousPageCommand = new DelegateCommand(PreviousPageAction);
NextPageCommand = new DelegateCommand(NextPageAction);
LastPageCommand = new DelegateCommand(LastPageAction);
ComboBoxSelectChange = new DelegateCommand(ComboBoxSelectAction);
}
private void ComboBoxSelectAction()
{
aggregator.UpdateLoading(true);
CurrentPage = 1;
switch (ComboBoxIndex)
{
case 0:
PageSize = 20;
break;
case 1:
PageSize = 50;
break;
case 2:
PageSize = 100;
break;
}
System.Diagnostics.Trace.WriteLine(pageSize);
TotalPage = FakeSource.Count / PageSize;
//点击事件
var result = FakeSource.Take(PageSize).ToList();
ResultFakeSource.Clear();
ResultFakeSource.AddRange(result);
aggregator.UpdateLoading(false);
}
private async void FirstPageAction()
{
aggregator.UpdateLoading(true);
CurrentPage = 1;
var result = FakeSource.Take(PageSize).ToList();
await Task.Delay(450);
ResultFakeSource.Clear();
ResultFakeSource.AddRange(result);
aggregator.UpdateLoading(false);
}
private async void PreviousPageAction()
{
aggregator.UpdateLoading(true);
if (CurrentPage == 1)
{
return;
}
List<FakeDatabase> result = new List<FakeDatabase>();
if (CurrentPage == 2)
{
result = FakeSource.Take(PageSize).ToList();
}
else
{
result = FakeSource.Skip((CurrentPage - 2) * PageSize).Take(pageSize).ToList();
}
await Task.Delay(450);
ResultFakeSource.Clear();
ResultFakeSource.AddRange(result);
CurrentPage--;
aggregator.UpdateLoading(false);
}
private async void NextPageAction()
{
aggregator.UpdateLoading(true);
if (CurrentPage == TotalPage)
{
return;
}
var result = FakeSource.Skip(CurrentPage * PageSize).Take(PageSize).ToList();
await Task.Delay(450);
ParseList(result);
ResultFakeSource.Clear();
ResultFakeSource.AddRange(result);
CurrentPage++;
aggregator.UpdateLoading(false);
}
private async void LastPageAction()
{
aggregator.UpdateLoading(true);
CurrentPage = TotalPage;
int skipCount = (TotalPage - 1) * PageSize;
int takeCount = FakeSource.Count - skipCount;
var result = FakeSource.Skip(skipCount).Take(takeCount).ToList();
await Task.Delay(450);
ResultFakeSource.Clear();
ResultFakeSource.AddRange(result);
aggregator.UpdateLoading(false);
}
public void InitialLoad()
{
for (int i = 0; i < 1000; i++)
{
FakeSource.Add(new FakeDatabase { ItemId = i, ItemName = "Demo_Page_" + i });
}
}
public void ParseList(List<FakeDatabase> result)
{
for (int i = 0; i < result.Count; i++)
{
FakeDatabase db = result[i];
System.Diagnostics.Trace.WriteLine(db.ItemId + "==" + db.ItemName);
}
}
}
}