使用MVVM写的WPF分页控件

首先声明,我是一个小菜鸟,学习WPF也就2个月,如果写的不对的地方,请批评指正。

因为想做一个WPF分页页面,网上找了很多示例程序,大部分都要求使用存储过称,与业务合在一起,控件的通用性不够强。

在我看来,分页控件只需要知道数据有多少页、当前是第几页就可以了,上一页、下一页等命令使用事件或者委托发送出去,实现控件与业务的分离。在这里我采用了MVVM模式来实现分页控件,使用MVVM一定要记住:数据驱动UI界面,尽可能不在后台代码中编写业务逻辑和界面逻辑。示例代码使用了Prism,请引用相关DLL。

首先新建一个自定义控件UserControl

 1 <UserControl x:Class="ZhuanKeWebTool.WPF.Content.UCPager"
 2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6              mc:Ignorable="d" 
 7              d:DesignHeight="30" d:DesignWidth="500">
 8     <Grid Background="AliceBlue">
 9         <Grid.ColumnDefinitions>
10             <ColumnDefinition Width="80" />
11             <ColumnDefinition Width="*" />
12             <ColumnDefinition Width="20" />
13             <ColumnDefinition Width="20" />
14             <ColumnDefinition Width="Auto" />
15             <ColumnDefinition Width="20" />
16             <ColumnDefinition Width="20" />
17         </Grid.ColumnDefinitions>
18         <StackPanel Orientation="Horizontal">
19             <TextBlock Text="" HorizontalAlignment="Left" Height="15" Margin="10,0,0,0"/>
20             <TextBlock Text="{Binding RecordCount}" VerticalAlignment="Center"/>
21             <TextBlock Text="" VerticalAlignment="Center"/>
22         </StackPanel>
23 
24         <Button Grid.Column="2" ToolTip="首页" Padding="0" Command="{Binding HomePageCommand}">
25             <Button.Content>
26                 <Image Width="12" Source="../Resources/Images/fastrewind.png"/>
27             </Button.Content>
28         </Button>
29         <Button Grid.Column="3" ToolTip="上一页" Padding="0" Command="{Binding PreviousPageCommand}">
30             <Button.Content>
31                 <Image Width="12" Source="../Resources/Images/skiprewind.png"/>
32             </Button.Content>
33         </Button>
34 
35         <WrapPanel Grid.Column="4" HorizontalAlignment="Center" VerticalAlignment="Center">
36             <TextBlock Text="" VerticalAlignment="Center"/>
37             <ComboBox ItemsSource="{Binding IndexList}" SelectedItem="{Binding PageIndex}" Width="50"/>
38             <TextBlock Text="" VerticalAlignment="Center"/>
39         </WrapPanel>
40 
41         <Button Grid.Column="5" ToolTip="下一页" Padding="0" Command="{Binding NextPageCommand}">
42             <Button.Content>
43                 <Image Width="12" Source="../Resources/Images/skipforward.png"/>
44             </Button.Content>
45         </Button>
46         <Button Grid.Column="6" ToolTip="尾页" Padding="0" Command="{Binding TailPageCommand}">
47             <Button.Content>
48                 <Image Width="12" Source="../Resources/Images/fastforward.png"/>
49             </Button.Content>
50         </Button>
51 
52     </Grid>
53 </UserControl>
View Code

控件的样子是这样的:

UserControl的后台代码:

 1 public partial class UCPager : UserControl
 2 {
 3     public UCPagerViewModel UCPagerViewModel { get; private set; }
 4 
 5     public UCPager()
 6     {
 7         InitializeComponent();
 8         UCPagerViewModel = new UCPagerViewModel();
 9         this.DataContext = UCPagerViewModel;
10     } 
11 
12 }

后台代码很简单,实例化一个ViewModel,把ViewModel作为属性是想让使用者可以更改ViewModel的属性,达到更改分页控件的目的。

UCPagerViewModel.CS

/// 申明委托
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
public delegate void EventPagingHandler(EventPagingArg e);

/// <summary>
/// 自定义事件参数
/// </summary>
public class EventPagingArg : EventArgs
{
    public int PageIndex { get; set; }

    public EventPagingArg(int pageIndex)
    {
        PageIndex = pageIndex;
    }
}

public class UCPagerViewModel : NotificationObject
{
    #region 构造器

    public UCPagerViewModel()
    {
        NextPageCommand = new DelegateCommand(new Action(NextPageCommandExecute));
        PreviousPageCommand = new DelegateCommand(new Action(PreviousPageCommandExecute));
        HomePageCommand = new DelegateCommand(new Action(HomePageCommandExecute));
        TailPageCommand = new DelegateCommand(new Action(TailPageCommandExecute));
    }

        
    #endregion

    #region Property
    private int pageIndex;

    public int PageIndex
    {
        get { return pageIndex; }
        set 
        { 
            pageIndex = value;
            this.RaisePropertyChanged("PageIndex");
            if (PagingHandler != null)
                PagingHandler.Invoke(new EventPagingArg(PageIndex));
        }
    }

    private int pageSize;

    public int PageSize
    {
        get { return pageSize; }
        set { pageSize = value; this.RaisePropertyChanged("PageSize"); }
    }

    private int pageCount;

    public int PageCount
    {
        get { return pageCount; }
        set { pageCount = value; this.RaisePropertyChanged("PageCount"); }
    }

    private int recordCount;

    public int RecordCount
    {
        get { return recordCount; }
        set { recordCount = value; this.RaisePropertyChanged("RecordCount"); }
    }

    private List<int> indexList;

    public List<int> IndexList
    {
        get { return indexList; }
        set { indexList = value; this.RaisePropertyChanged("IndexList"); }
    }

    #endregion

    #region 命令

    public DelegateCommand NextPageCommand { get; set; }

    public DelegateCommand PreviousPageCommand { get; set; }

    public DelegateCommand HomePageCommand { get; set; }

    public DelegateCommand TailPageCommand { get; set; }

    private void NextPageCommandExecute()
    {
        if(PageIndex<PageCount)
            PageIndex = PageIndex + 1;
    }
    private void PreviousPageCommandExecute()
    {
        if (PageIndex >1)
            PageIndex = PageIndex - 1;
    }
    private void HomePageCommandExecute()
    {
        PageIndex = 1;
    }
    private void TailPageCommandExecute()
    {
        PageIndex = PageCount;
    }

    #endregion

    #region 事件

    public EventPagingHandler PagingHandler { get; set; }

    #endregion
}
View Code

UCPagerViewModel.CS包含三个部分,定义了一个委托、一个事件参数和ViewModel。使用该控件时先向其传入PageIndex、PageCount、RecordCount、PageSize和IndexList参数控制控件的现实,同时注册一个委托,当按下按钮或者选择页码时,分页控件会调用注册的委托,同时传递选择的页码。

分页控件使用示例:

<StackPanel>
    <DataGrid x:Name="emailDataGrid" ItemsSource="{Binding EmailList}" AutoGenerateColumns="False" VerticalGridLinesBrush="Red"
                BorderBrush="DarkBlue" BorderThickness="1" LoadingRow="emailDataGrid_LoadingRow" CanUserAddRows="False" IsReadOnly="True">
        <DataGrid.Columns>
            <DataGridTextColumn Header="用户名" Width="100" Binding="{Binding UserName}"/>
            <DataGridTextColumn Header="密码" Width="*" Binding="{Binding Password}"/>
        </DataGrid.Columns>
    </DataGrid>
    <local:UCPager x:Name="mailPager"/>
</StackPanel>

后台代码:

public partial class NetsMail : UserControl
{
    public NetsMail()
    {
        InitializeComponent();

        UCPagerViewModel pagerViewModel = this.mailPager.UCPagerViewModel;
        NetsMailViewModel model = new NetsMailViewModel(pagerViewModel);
        this.DataContext = model;
    }

    private void emailDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
    {
        e.Row.Header = e.Row.GetIndex() + 1;
    }
}

在后台代码中,首先获取分页控件的ViewModel,然后将分页控件的ViewModel传入自己的ViewModel

public NetsMailViewModel(UCPagerViewModel model)
{
    pagerViewModel = model;
    pagerViewModel.PagingHandler += new EventPagingHandler(e=>PageIndex=e.PageIndex);
    NetsService = App.Container.GetExportedValue<INetsDesktopContract>();

    int recordCount;
    PageIndex = 1;
    emailList = NetsService.GetEmailAccounts(PageIndex, 20, out recordCount);

    pagerViewModel.PageIndex = PageIndex;
    pagerViewModel.PageSize = 20;
    pagerViewModel.RecordCount = recordCount;
    pagerViewModel.PageCount = recordCount % 20 > 0 ? recordCount / 20 + 1 : recordCount / 20;

    List<int> indexList = new List<int>();
    for (int i = 0; i < pagerViewModel.PageCount; i++)
    {
        indexList.Add(i + 1);
    }
    pagerViewModel.IndexList = indexList;
}

在ViewModel中获取用于显示的数据,同时向分页控件传入显示需要的数据。注意

pagerViewModel.PagingHandler += new EventPagingHandler(e=>PageIndex=e.PageIndex);

这句话,主要作用是注册一个委托,用于获取分页控件传递过来的PageIndex。


原文地址:https://www.cnblogs.com/Leman/p/3392636.html