自定義WPF分頁控件的全過程記錄
一、分頁控件功能說明#
實(shí)現(xiàn)如上圖所示的分頁控件,需要實(shí)現(xiàn)一下幾個(gè)功能:
- 可以設(shè)置每頁能夠展示的最大列數(shù)(例如每頁8列、每頁16列等等)。
- 加載的數(shù)組總數(shù)量超過設(shè)置的每頁列數(shù)后,需分頁展示。
- 可以直接點(diǎn)擊指定的列數(shù)或者上下頁按鈕進(jìn)行頁面跳轉(zhuǎn)
二、自定義分頁控件使用說明#
為了實(shí)現(xiàn)以上功能,主要進(jìn)行以下工作:
1、添加一個(gè)自定義按鈕PagerButton類,聲明一個(gè)依賴屬性IsActive,用于記錄當(dāng)前頁面所在頁數(shù)的按鈕,此時(shí)該按鈕邊框高亮顯示,具體代碼如下:
public class PagerButton : Button { public bool IsActive { get { return (bool)GetValue(IsActiveProperty); } set { SetValue(IsActiveProperty, value); } } public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register("IsActive", typeof(bool), typeof(PagerButton), new PropertyMetadata(false)); }
<Style x:Key="PagerButtonStyle" TargetType="controls:PagerButton"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="controls:PagerButton"> <Border x:Name="b1" CornerRadius="2" Background="{StaticResource Themes}" BorderThickness="1" BorderBrush="{StaticResource Disabled}" Width="32" Height="32" Margin="4,0"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="b1" Property="BorderBrush" Value="{StaticResource Accent}"></Setter> </Trigger> <Trigger Property="IsActive" Value="True"> <Setter TargetName="b1" Property="BorderBrush" Value="{StaticResource Accent}"></Setter> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> </Style.Triggers> </Style>
2、添加自定義分頁控件PagerBar類,用于展示分頁按鈕(使用PagerButton類)和實(shí)現(xiàn)分頁跳轉(zhuǎn),需要定義當(dāng)前頁面、總頁數(shù)、設(shè)置的每頁最大列數(shù)三個(gè)依賴屬性,具體如下:
public int CurrentPageIndex { get { return (int)GetValue(CurrentPageIndexProperty); } set { SetValue(CurrentPageIndexProperty, value); } } public int PageSize { get { return (int)GetValue(PageSizeProperty); } set { SetValue(PageSizeProperty, value); } } public int PageCount { get { return (int)GetValue(PageCountProperty); } set { SetValue(PageCountProperty, value); } } public static readonly DependencyProperty CurrentPageIndexProperty = DependencyProperty.Register("CurrentPageIndex", typeof(int), typeof(PagerBar), new PropertyMetadata(-1, CurrentPageIndexPropertyChangedCallback)); public static readonly DependencyProperty PageSizeProperty = DependencyProperty.Register("PageSize", typeof(int), typeof(PagerBar), new PropertyMetadata(10, PageSizePropertyChangedCallback)); public static readonly DependencyProperty PageCountProperty = DependencyProperty.Register("PageCount", typeof(int), typeof(PagerBar), new PropertyMetadata(-1, PageCountPropertyChangedCallback));
3、添加一個(gè)工具類Pager,用于將數(shù)據(jù)按照要求分頁,該工具類聲明當(dāng)前頁數(shù)、總頁數(shù)、設(shè)置的每頁最大列數(shù)三個(gè)屬性,具體如下:
public int PageSize { get => _pageSize; set { if (value == _pageSize) return; _pageSize = value; OnPropertyChanged(); SetPageSize(_pageSize); } } public int PageCount { get => _pageCount; set { if (value == _pageCount) return; _pageCount = value; // 最少頁為1頁 if (_pageCount == 0) _pageCount = 1; OnPropertyChanged(); } } public int CurPageIndex { get => _curPageIndex; set { if (value == _curPageIndex) return; _curPageIndex = value; OnPropertyChanged(); GotoPageOf(_curPageIndex); } }
4、將Pager類和PageBar控件進(jìn)行數(shù)據(jù)綁定。具體操作為:在綁定的ViewModel上聲明一個(gè)Pager類,然后將該P(yáng)ager類的屬性和PagrBar進(jìn)行一一對(duì)應(yīng)綁定。具體代碼如下:
<controls:PagerBar Grid.Row="1" Margin="5" HorizontalAlignment="Center" PageSize="{Binding Path=Pager.PageSize, Mode=TwoWay}" PageCount="{Binding Path=Pager.PageCount, Mode=TwoWay}" CurrentPageIndex="{Binding Path=Pager.CurPageIndex, Mode=TwoWay}"></controls:PagerBar>
5、初始化Pager類時(shí),在界面綁定的ViewModel里面重新聲明一個(gè)數(shù)組,用于保存分頁后的數(shù)組,將該數(shù)組綁定到待展示的條目控件(例如ListBox)上,具體如下:
StudentCollection=new ObservableCollection<Student>(); for (int i = 0; i < 10; i++) { StudentCollection.Add(new Student() { Id = Index = i, Source = 10 * (i + 1), }); } AddCommand =new RelayCommand(ExecuteAddCommand); DeleteCommand=new RelayCommand(ExecuteDeleteCommand); SortCommand=new RelayCommand(ExecuteSortCommand); Pager=new Pager<Student>(8,StudentCollection); Pager.PagerUpdated += items => { StudentCollectionPaging = new ObservableCollection<Student>(items); }; Pager.CurPageIndex = 1; <ListBox x:Name="ListBoxStudent" Grid.Row="0" ItemsSource="{Binding StudentCollectionPaging}" ItemTemplate="{StaticResource StudentDateTemplate}"></ListBox>
三、總結(jié)說明#
為了實(shí)現(xiàn)綁定的數(shù)組添加、刪除時(shí),PageBar分組控件也能立即更新控件,Pager工具類增加以下構(gòu)造函數(shù),首先保證數(shù)組為同一引用,其次使用ObservableCollection保證界面和ViewModel即時(shí)更新:
public Pager(int pageSize, ObservableCollection<T> source) { _pageSize = pageSize; _itemsSource = source; _itemsSource.CollectionChanged += ItemsSourceOnCollectionChanged; CalculatePaging(); } private void ItemsSourceOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { CalculatePaging(); GotoPageOf(CurPageIndex); }
四、示例源碼#
示例源碼地址:分頁控件源碼
五、問題#
在實(shí)際應(yīng)用中,發(fā)現(xiàn)如下問題:當(dāng)需要對(duì)綁定的整個(gè)數(shù)組進(jìn)行排序時(shí),由于Pager類初始化傳入的數(shù)組必須和實(shí)際數(shù)為同一個(gè)引用且必須為ObservableCollection數(shù)組,那么使用LINQ排序完成后,必須要使用ToList進(jìn)行轉(zhuǎn)換,就必須重新初始化ObservableCollection,那么后續(xù)當(dāng)該ObservableCollection數(shù)組變化時(shí),也無法通知到Pager類的數(shù)組了。為了解決該問題,想到以下兩個(gè)方法:
(1)自定義排序,針對(duì)ObservableCollection的每個(gè)數(shù)組對(duì)象進(jìn)行排序。這樣排序完成后ObservableCollection引用無變化。
(2)先用臨時(shí)變量保存排序完成的數(shù)組,然后清空ObservableCollection,然后再迭代添加臨時(shí)數(shù)組。如此,ObservableCollection對(duì)象前后也為統(tǒng)一引用。
public ICommand SortCommand { get; set; } private void ExecuteSortCommand(object obj) { var list = StudentCollection.ToList().OrderByDescending(item=>item.Source).ToList(); StudentCollection.Clear(); foreach (var item in list) { StudentCollection.Add(item); } }
目前暫時(shí)采用了第二種方法,但該方法效率不高。后續(xù)有更好的解決方法可以留言討論。
總結(jié)
到此這篇關(guān)于自定義WPF分頁控件的文章就介紹到這了,更多相關(guān)自定義WPF分頁控件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實(shí)現(xiàn)Bitmap類型與Byte[]類型相互轉(zhuǎn)化的示例詳解
在C#編程中,Bitmap類型和Byte[]類型之間的相互轉(zhuǎn)化是圖像處理和數(shù)據(jù)傳輸中常見的需求,Bitmap類型表示一個(gè)位圖圖像,而Byte[]類型則是一個(gè)字節(jié)數(shù)組,本文將詳細(xì)介紹如何在這兩種類型之間進(jìn)行相互轉(zhuǎn)化,需要的朋友可以參考下2024-07-07Unity?UGUI的VerticalLayoutGroup垂直布局組件介紹使用
這篇文章主要為大家介紹了Unity?UGUI的VerticalLayoutGroup垂直布局組件介紹使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07基于c#實(shí)現(xiàn)的九九乘法表(簡(jiǎn)單實(shí)例)
本文主要分享了基于c#實(shí)現(xiàn)的九九乘法表,代碼簡(jiǎn)潔,需要的朋友可以參考下,希望對(duì)大家有所幫助2016-12-12無法從 int? 轉(zhuǎn)換為 int 運(yùn)行時(shí)出現(xiàn)錯(cuò)誤
無法從"int?"轉(zhuǎn)換為"int" ,在運(yùn)行時(shí)會(huì)出現(xiàn)錯(cuò)誤,通過強(qiáng)制類型轉(zhuǎn)換(int)便可解決2014-05-05