自定义控件DataPager

   在最近的一个项目中,涉及到一个自定义翻页控制的控件,下面就这一个控件做详细的说明,这个自定义控件的主要作用是对数据源进行翻页控制,比如说:“上一页、下一页、首页、末页”等相关操作,由于在一个项目中有多个界面要用到这一部分,所以我们将其封装成一个自定义控件,从而使软件整体结构更加清楚明了,首先我们来将控件的界面展示出来。

    整个控件可以分成三个部分,最左边是一个Combobox控件,中间是常见的上一页、下一页、向前、向后操作,最右边是显示当前记录。下面我们重点来介绍中间部分的封装,在这里我们将每一个按钮封装成一个ImageButton控件,这里我们贴出相应的前台、后台代码,从而从整体上进行分析。   

<Button x:Class="CustomControlLibrary.ImageButton"
             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" 
             mc:Ignorable="d" x:Name="loc"
             d:DesignHeight="44" d:DesignWidth="75">
    <Button.Resources>
        <ResourceDictionary Source="Themes/Generic.xaml" />
    </Button.Resources>
    <Image Name="innerImage" Source="{Binding ImageSource,ElementName=loc}" Stretch="None" />
</Button>

  这里前台的代码比较简单,我们将Button的样式写在了一个资源字典中,同时在Button上面放置一个Image控件,从而组成我们的ImageButton控件,在后台的代码中我们主要定义了两个依赖项属性,ImageSource和GrayImageSource,ImageSource是当按钮正常使用的时候,其显示的背景,GrayImageSource是当按钮的IsEnable=false的时候,其显示的背景,这里先贴出其后台代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 CustomControlLibrary {
    /// <summary>
    /// ImageButton.xaml 的交互逻辑
    /// </summary>
    public partial class ImageButton : Button 
{ public ImageButton()
{ InitializeComponent(); this.Style = this.FindResource("ImageButtonStyle") as Style; this.IsEnabledChanged += new DependencyPropertyChangedEventHandler(ImageButton_IsEnabledChanged); } void ImageButton_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{ if (this.IsEnabled && ImageSource != null)
{ innerImage.Source = ImageSource; } else if (!this.IsEnabled && GrayImageSource != null)
{ innerImage.Source = GrayImageSource; } }
public ImageSource ImageSource
{ get { return (ImageSource)GetValue(ImageSourceProperty); } set { SetValue(ImageSourceProperty, value); } } // Using a DependencyProperty as the backing store for ImageSource. This enables animation, styling, binding, etc... public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata(null));
public ImageSource GrayImageSource
{ get { return (ImageSource)GetValue(GrayImageSourceProperty); } set { SetValue(GrayImageSourceProperty, value); } } // Using a DependencyProperty as the backing store for GrayImageSource. This enables animation, styling, binding, etc... public static readonly DependencyProperty GrayImageSourceProperty = DependencyProperty.Register("GrayImageSource", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata(null)); public override void OnApplyTemplate()
{ base.OnApplyTemplate(); if (this.IsEnabled && ImageSource != null)
{
innerImage.Source = ImageSource; } else if (!this.IsEnabled && GrayImageSource != null)
{ innerImage.Source = GrayImageSource; } } } }

  这里首先分析一下WPF的依赖项属性和普通的.net属性有什么不同,依赖属性是WPF平台中一个新增的概念,出现的目的是用来实现WPF中的样式、自动绑定及实现动画等特性。依赖属性的出现是WPF这种特殊的呈现原理派生出来的,与.NET普通属性不同的是,依赖属性的值是依靠多个提供程序来判断的,并且其具有内建的传递变更通知的能力。

依赖属性的定义与普通的.NET属性的定义有区别,普通的.NET属性定义只需要定义其set和get区块的赋值与设置即可,而依赖属性需要向.NET的属性系统进行注册。这里我们定义了ImageSource和GrayImageSource两个依赖项属性。另外这里还重写了基类的OnApplyTemplate方法,这个方法是FrameworkElement中定义的方法,在派生类中重写后,每当应用程序代码或内部进程调用 ApplyTemplate,都将调用此方法。FrameworkElement 派生类可以使用 OnApplyTemplate 类处理程序获知显式调用或由布局系统调用此方法的情况。OnApplyTemplate 在完全生成模板并将其附加到逻辑树之后调用。

    然后就是具体的DataPager控件的实现了,这里也分别贴出相应的前台和后台的代码。

    

<UserControl x:Class="CustomControlLibrary.DataPager"  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:loc="clr-namespace:CustomControlLibrary"
             x:Name="dp" Margin="3"
             mc:Ignorable="d" 
             d:DesignHeight="46" d:DesignWidth="590" Loaded="DataPager_Loaded">  
    <Grid>
        <!--<Grid.Resources>
            <Style TargetType="{x:Type Image}">
                <Setter Property="Margin" Value="3,0,3,0" />
                <Setter Property="Cursor" Value="Hand" />
            </Style>
        </Grid.Resources>-->
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <ComboBox Grid.Column="0"  VerticalAlignment="Center" Name="cboPageSize"
                  MinWidth="40" Margin="5,0,0,0"   ItemsSource="{Binding Path=PageSizeItems,ElementName=dp}" 
                  SelectedItem="{Binding PageSize,Mode=TwoWay,ElementName=dp}" SelectionChanged="cbpPageSize_SelectionChanged"  Visibility="Visible"/>
        <StackPanel Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal" Margin="5,0,0,0">
            <loc:ImageButton Click="btnFirst_Click" x:Name="btnFirst"
                ImageSource="/CustomControlLibrary;component/Images/pagination_first.gif" 
                GrayImageSource="/CustomControlLibrary;component/Images/pagination_first_gray.gif" />
            <loc:ImageButton Click="btnPrev_Click" x:Name="btnPrev"
                ImageSource="/CustomControlLibrary;component/Images/pagination_prev.gif" 
                GrayImageSource="/CustomControlLibrary;component/Images/pagination_prev_gray.gif" />
            <TextBlock Text="第页 "  VerticalAlignment="Center"/>
            <TextBox Width="30" Text="{Binding Path=PageIndex,ElementName=dp}" Name="tbPageIndex" PreviewKeyDown="tbPageIndex_PreviewKeyDown" LostFocus="tbPageIndex_LostFocus" />
            <TextBlock Text=" 共 "  VerticalAlignment="Center"/>
            <TextBlock Text="{Binding Path=PageCount, ElementName=dp}"  VerticalAlignment="Center"/>
            <loc:ImageButton Click="btnNext_Click" x:Name="btnNext"
                ImageSource="/CustomControlLibrary;component/Images/pagination_next.gif" 
                GrayImageSource="/CustomControlLibrary;component/Images/pagination_next_gray.gif" />
            <loc:ImageButton Click="btnLast_Click" x:Name="btnLast"
                ImageSource="/CustomControlLibrary;component/Images/pagination_last.gif" 
                GrayImageSource="/CustomControlLibrary;component/Images/pagination_last_gray.gif" />
            <!--<loc:ImageButton Click="btnRefresh_Click"
                ImageSource="/CustomControlLibrary;component/Images/pagination_load.png"  Visibility="Hidden"/>-->
        </StackPanel>
        <TextBlock Grid.Column="2" VerticalAlignment="Center" Margin="5,0,5,0" >显示记录 
            <TextBlock Text="{Binding Path=Start,ElementName=dp}" /> 到 <TextBlock Text="{Binding Path=End,ElementName=dp}"/> 共 <TextBlock Text="{Binding Path=Total,ElementName=dp}"/> 条记录
        </TextBlock>
    </Grid>
</UserControl>

  这里重点介绍后台的逻辑代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
using System.ComponentModel;

namespace CustomControlLibrary {
    /// <summary>
    /// DataPager.xaml 的交互逻辑
    /// </summary>
    public partial class DataPager : UserControl, INotifyPropertyChanged 
    {
        public DataPager() 
        {
            InitializeComponent();
        }

        #region 依赖属性和事件
        public string PageSizeList
        {
            get { return (string)GetValue(PageSizeListProperty); }
            set { SetValue(PageSizeListProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PageSizeList.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PageSizeListProperty =
            DependencyProperty.Register("PageSizeList", typeof(string), typeof(DataPager), new UIPropertyMetadata("5,10,20", (s, e) =>
            {
                DataPager dp = s as DataPager;
                if (dp.PageSizeItems == null) 
                    dp.PageSizeItems = new List<int>();
                else 
                    dp.PageSizeItems.Clear();
                dp.RaisePropertyChanged("PageSizeItems");
            }));

        public int PageSize 
        {
            get { return (int)GetValue(PageSizeProperty); }
            set { SetValue(PageSizeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PageSize.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PageSizeProperty =
            DependencyProperty.Register("PageSize", typeof(int), typeof(DataPager), new UIPropertyMetadata(16));

        public int Total 
        {
            get { return (int)GetValue(TotalProperty); }
            set { SetValue(TotalProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Total.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TotalProperty =
            DependencyProperty.Register("Total", typeof(int), typeof(DataPager), new UIPropertyMetadata(0));

        public int PageIndex 
        {
            get { return (int)GetValue(PageIndexProperty); }
            set { SetValue(PageIndexProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PageIndex.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PageIndexProperty =
            DependencyProperty.Register("PageIndex", typeof(int), typeof(DataPager), new UIPropertyMetadata(1));
       

        public IEnumerable<object> ItemsSource 
        {
            get { return (IEnumerable<object>)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        /// <summary>
        /// ItemsSource数据源
        /// </summary>
        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IEnumerable<object>), typeof(DataPager), new UIPropertyMetadata(null));        

        public static readonly RoutedEvent PageChangedEvent = EventManager.RegisterRoutedEvent("PageChanged", RoutingStrategy.Bubble, typeof(PageChangedEventHandler), typeof(DataPager));
        /// <summary>
        /// 分页更改事件
        /// </summary>
        public event PageChangedEventHandler PageChanged
        {
            add 
            {
                AddHandler(PageChangedEvent, value);
            }
            remove 
            {
                RemoveHandler(PageChangedEvent, value);
            }
        }
        #endregion


        #region 通知属性
        private List<int> _pageSizeItems;
        /// <summary>
        /// 显示每页记录数集合
        /// </summary>
        public List<int> PageSizeItems 
        {
            get 
            {
                if (_pageSizeItems == null) 
                {
                    _pageSizeItems = new List<int>();
                }
                if (PageSizeList != null) 
                {
                    List<string> strs = PageSizeList.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                    _pageSizeItems.Clear();
                    strs.ForEach(c => {
                        _pageSizeItems.Add(Convert.ToInt32(c));
                    });
                }
                return _pageSizeItems;
            }
            set 
            {
                if (_pageSizeItems != value) 
                {
                    _pageSizeItems = value;
                    RaisePropertyChanged("PageSizeItems");
                }
            }
        }

        private int _pageCount;
        /// <summary>
        /// 总页数
        /// </summary>
        public int PageCount
        {
            get { return _pageCount; }
            set 
            {
                if (_pageCount != value)
                {
                    _pageCount = value;
                    RaisePropertyChanged("PageCount");
                }
            }
        }

        private int _start;
        /// <summary>
        /// 开始记录数
        /// </summary>
        public int Start 
        {
            get { return _start; }
            set 
            {
                if (_start != value) 
                {
                    _start = value;
                    RaisePropertyChanged("Start");
                }
            }
        }

        private int _end;
        /// <summary>
        /// 结束记录数
        /// </summary>
        public int End
        {
            get { return _end; }
            set 
            {
                if (_end != value)
                {
                    _end = value;
                    RaisePropertyChanged("End");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string propertyName) 
        {
            if (PropertyChanged != null) 
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

        #region 字段、属性、委托
        public delegate void PageChangedEventHandler(object sender, PageChangedEventArgs args);
        private PageChangedEventArgs pageChangedEventArgs; 
        #endregion

        #region 引发分页更改事件
        /// <summary>
        /// 引发分页更改事件
        /// </summary>
        private void RaisePageChanged() 
        {
            if (pageChangedEventArgs == null) 
            {
                pageChangedEventArgs = new PageChangedEventArgs(PageChangedEvent, PageSize, PageIndex);
            } 
            else 
            {
                pageChangedEventArgs.PageSize = this.PageSize;
                pageChangedEventArgs.PageIndex = this.PageIndex;
            }
            RaiseEvent(pageChangedEventArgs);
            //calc start、end
            if (ItemsSource != null) 
            {
                int curCount = ItemsSource.Count();
                Start = (PageIndex - 1) * PageSize + 1;
                End = Start + curCount - 1;

                if (Total % PageSize != 0) 
                {
                    PageCount = Total / PageSize + 1;
                } 
                else 
                {
                    PageCount = Total / PageSize;
                }
            } 
            else 
            {
                Start = End = PageCount = Total = 0;
            }
            //调整图片的显示
            btnFirst.IsEnabled = btnPrev.IsEnabled = (PageIndex != 1);
            btnNext.IsEnabled = btnLast.IsEnabled = (PageIndex != PageCount);
        } 
        #endregion

        #region 分页操作事件
        void DataPager_Loaded(object sender, RoutedEventArgs e)
        {
            RaisePageChanged();
        }

        private void cbpPageSize_SelectionChanged(object sender, SelectionChangedEventArgs e) 
        {
            if (this.IsLoaded) 
            {
                PageSize = (int)cboPageSize.SelectedItem;
                RaisePageChanged();
            }
        }

        private void btnFirst_Click(object sender, RoutedEventArgs e) 
        {
            PageIndex = 1;
            RaisePageChanged();
        }

        private void btnPrev_Click(object sender, RoutedEventArgs e) 
        {
            if (PageIndex > 1) 
            {
                --PageIndex;
            }
            RaisePageChanged();
        }

        private void btnNext_Click(object sender, RoutedEventArgs e) 
        {
            if (Total % PageSize != 0) 
            {
                PageCount = Total / PageSize + 1;
            } 
            else 
            {
                PageCount = Total / PageSize;
            }

            if (PageIndex < PageCount) 
            {
                ++PageIndex;
            }
            RaisePageChanged();
        }

        private void btnLast_Click(object sender, RoutedEventArgs e) 
        {
            if (Total % PageSize != 0) 
            {
                PageCount = Total / PageSize + 1;
            } 
            else
            {
                PageCount = Total / PageSize;
            }
            PageIndex = PageCount;
            RaisePageChanged();
        }

        private void btnRefresh_Click(object sender, RoutedEventArgs e) 
        {
            RaisePageChanged();
        }

        private void tbPageIndex_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter) 
            {
                tbPageIndex_LostFocus(sender, null);
            }
        }

        private void tbPageIndex_LostFocus(object sender, RoutedEventArgs e) 
        {
            int pIndex = 0;
            try 
            {
                pIndex = Convert.ToInt32(tbPageIndex.Text);
            } catch { pIndex = 1; }

            if (pIndex < 1) PageIndex = 1;
            else if (pIndex > PageCount) PageIndex = PageCount;
            else PageIndex = pIndex;

            RaisePageChanged();
        } 
        #endregion 
        
    }

    /// <summary>
    /// 分页更改参数
    /// </summary>
    public class PageChangedEventArgs : RoutedEventArgs
    {
        public int PageSize { get; set; }
        public int PageIndex { get; set; }

        public PageChangedEventArgs(RoutedEvent routeEvent, int pageSize, int pageIndex)
            : base(routeEvent) 
        {
            this.PageSize = pageSize;
            this.PageIndex = pageIndex;
        }
    }
}

  这里定义了一些该控件要使用的一些属性,PageSize属性用于定义每一页中的项的数量,Total属性定义总共有多少项,PageIndex定义当前的页码,ItemsSource用于定义数据源的集合,类型是IEnumerable<object>类型,这个里面定义的最重要的函数是RaisePageChanged,该函数将引发分页更改事件,在这个函数中我们将当前定义的路由事件PageChangedEvent,以及每一页项目的大小,以及当前页码传递到PageChangedEventArgs的一个对象中,然后调用RaiseEvent来引发特定的路由事件,这里需要注意的是必须将当前定义的路由事件传递到基类RoutedEventArgs中,否则不能触发该路由事件。

 

转载于:https://www.cnblogs.com/seekdream/p/4843927.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
九头鸭.net分页控件DataPage的主要功能: 1、支持通过Url进行分页: DataPage除提供默认的类似于DataGrid和GridView的PostBack分页方式外,还支持通过Url进行分页,象大多数asp程序中分页一样, Url分页方式允许用户通过在浏览器地址栏中输入相应的地址即可直接进入指定页面,也可以使搜索引擎搜索到所有分页的页面的内容,因此具有用户友好和搜索引擎友好的优点,关于Url分页与PostBack分页方式的差异,请参考Url与PostBack分页方式的对比。 2、支持Url分页方式下的Url重写(UrlRewrite)功能 Url重写技术可以使显示给用户的Url不同于实际的Url,Url重写技术被广泛应用于搜索引擎优化(SEO)、网站重组后重定向页面路径以及提供用户友好的Url等方面, DataPage支持Url重写技术使您可以自定义分页导航的Url格式,实现Url重写; 3、支持使用用户自定义图片做为导航元素: 您可以使用自定义的图片文件做为分页控件的导航元素,而不仅仅限于显示文字内容。 4、功能强大灵活、使用方便、可定制性强: DataPage分页控件的所有导航元素都可以由用户进行单独控制,支持使用26种分页皮肤样式 5、增强的 Visual Studio 2005/2008设计时支持 增强的设计时支持使控件在设计时更加直观,易于使用,开发快捷方便。 6、兼容IE6.0 及FireFox 1.5 等浏览器 7、丰富而完整的控件文档和示例项目: 控件附带的完整的帮助文档及示例项目能够帮助您快速上手,熟悉DataPage控件的使用,您还可以通过给作者留言以及论坛提问等方式解决控件使用中遇到的问题。 8、DataPage分页效率高效除了默认实例access外如果选择sqlserver存储过程分页将会更高效

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值