wpf 自定义控件(包含依赖属性以及事件)

wpf  事件https://blog.csdn.net/weixin_44240082/article/details/99062899   

创建了这个依赖属性,就可以直接在对应的控件中使用了,就像是button中一开始就内置的width等属性一样,这个在设计自定义控件的时候用的尤其多

https://www.cnblogs.com/yang-fei/p/4724899.html   分页

下面讲的是自定义分页控件代码:

<UserControl x:Class="WPFDataGridPaging.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:local="clr-namespace:WPFDataGridPaging"
             mc:Ignorable="d" 
             d:DesignHeight="30" d:DesignWidth="220">
    <UserControl.Resources>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Width" Value="22"/>
            <Setter Property="Height" Value="22"/>
        </Style>
    </UserControl.Resources>
    <Grid>
        <StackPanel Orientation="Horizontal">
            <Button x:Name="FirstPageButton" Margin="5,0" Click="FirstPageButton_Click">
                <Path Width="7" Height="10" Data="M0,0L0,10 M0,5L6,2 6,8 0,5" Stroke="Black" StrokeThickness="1" 
Fill
="Black" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Button> <Button x:Name="PreviousPageButton" Margin="0,0,5,0" Click="PreviousPageButton_Click"> <Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="Black" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Button> <TextBlock VerticalAlignment="Center"> <Run Text="第"/> <Run x:Name="rCurrent" Text="0"/> <Run Text="页"/> </TextBlock> <Button Margin="5,0" x:Name="NextPageButton" Click="NextPageButton_Click"> <Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="Black" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center"> <Path.RenderTransform> <RotateTransform Angle="180" CenterX="4" CenterY="4" /> </Path.RenderTransform> </Path> </Button> <Button Margin="0,0,5,0" x:Name="LastPageButton" Click="LastPageButton_Click"> <Path x:Name="MainPath" Width="7" Height="10" Data="M0,0L0,10 M0,5 L6,2 6,8 0,5"

Stroke="Black" StrokeThickness="1" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center"> <Path.RenderTransform> <RotateTransform Angle="180" CenterX="3" CenterY="5" /> </Path.RenderTransform> </Path> </Button> <TextBlock VerticalAlignment="Center"> <Run Text="共"/> <Run x:Name="rTotal" Text="0"/> <Run Text="页"/> </TextBlock> </StackPanel> </Grid> </UserControl>

 

界面:

 

 

 

后台代码:

 public partial class Pager : UserControl
    {
        #region 声明事件和依赖属性 
        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;
        #endregion

        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()
        {
            #region 注册事件以及依赖属性
            //注册FirstPageEvent事件,事件的拥有者是Pager,路由事件的名称是FirstPage,这是唯一的
            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))); #endregion } 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); } } /// <summary> /// 依赖属性回调方法 /// </summary> /// <param name="d"></param> /// <param name="e"></param> 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)); } }

 

 

 上面就是自定义的一个分页控件,如果我们想要使用这个控件,如下:

<Window x:Class="WPFDataGridPaging.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:local="clr-namespace:WPFDataGridPaging"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <DataGrid Grid.Row="0" ItemsSource="{Binding FakeSource}" AutoGenerateColumns="False" CanUserAddRows="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Item Id" Binding="{Binding Id}" Width="80"/>
                <DataGridTextColumn Header="Item Name" Binding="{Binding ItemName}" Width="180"/>
            </DataGrid.Columns>
        </DataGrid>
        <!-- TotalPage 和CurrentPage就是在Pager中自定义的依赖属性,可以在这里直接来用-->
        <local:Pager TotalPage="{Binding TotalPage}"
                     CurrentPage="{Binding CurrentPage, Mode=TwoWay}" 
                     HorizontalAlignment="Center"
                     Grid.Row="1">
            <i:Interaction.Triggers>
                <!--EventName="FirstPage"  这里FirstPage就是前面注册事件的时候默认的事件名称,必须要唯一 -->
                <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>
</Window>

 

界面:

 

 

 后台代码:

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //这里一定要注意,一定要将模型加到上下文中,要不然依赖属性和事件都不会触发,在实际开发中是不可能一打开
            //界面就开始加载出来数据的,所以可以通过ObservableCollection形式绑定表格数据,
            //而需要绑定事件和依赖属性的需要将其绑定到上下文中
            DataContext = new MainViewModel();
        }
    }

 

MainViewModel:

 public class MainViewModel : ViewModel
    {
        private ICommand _firstPageCommand;

        public ICommand FirstPageCommand
        {
            get
            {
                return _firstPageCommand;
            }

            set
            {
                _firstPageCommand = value;
            }
        }

        private ICommand _previousPageCommand;

        public ICommand PreviousPageCommand
        {
            get
            {
                return _previousPageCommand;
            }

            set
            {
                _previousPageCommand = value;
            }
        }

        private ICommand _nextPageCommand;

        public ICommand NextPageCommand
        {
            get
            {
                return _nextPageCommand;
            }

            set
            {
                _nextPageCommand = value;
            }
        }

        private ICommand _lastPageCommand;

        public ICommand LastPageCommand
        {
            get
            {
                return _lastPageCommand;
            }

            set
            {
                _lastPageCommand = value;
            }
        }

        private int _pageSize;

        public int PageSize
        {
            get
            {
                return _pageSize;
            }
            set
            {
                if(_pageSize != value)
                {
                    _pageSize = value;
                    OnPropertyChanged("PageSize");
                }
            }
        }

        private int _currentPage;

        public int CurrentPage
        {
            get
            {
                return _currentPage;
            }

            set
            {
                if(_currentPage != value)
                {
                    _currentPage = value;
                    OnPropertyChanged("CurrentPage");
                }
            }
        }

        private int _totalPage;

        public int TotalPage
        {
            get
            {
                return _totalPage;
            }

            set
            {
                if(_totalPage != value)
                {
                    _totalPage = value;
                    OnPropertyChanged("TotalPage");
                }
            }
        }
        /// <summary>
        /// ObservableCollection表示一个动态数据集合,它可在添加、删除项目或刷新整个列表时提供通知。
        /// 在xaml中绑定FakeSource之后,运行中FakeSource这里的数据改变的话
        /// </summary>
        private ObservableCollection<FakeDatabase> _fakeSoruce;

        public ObservableCollection<FakeDatabase> FakeSource
        {
            get
            {
                return _fakeSoruce;
            }
            set
            {
                if(_fakeSoruce != value)
                {
                    _fakeSoruce = value;
                    OnPropertyChanged("FakeSource");
                }
            }
        }

        private List<FakeDatabase> _source;

        public MainViewModel()
        {
            _currentPage = 1;

            _pageSize = 20;

            FakeDatabase fake = new FakeDatabase();

            _source = fake.GenerateFakeSource();

            _totalPage = _source.Count / _pageSize;

            _fakeSoruce = new ObservableCollection<FakeDatabase>();

            List<FakeDatabase> result = _source.Take(20).ToList();

            _fakeSoruce.Clear();

            _fakeSoruce.AddRange(result);

            _firstPageCommand = new DelegateCommand(FirstPageAction);

            _previousPageCommand = new DelegateCommand(PreviousPageAction);

            _nextPageCommand = new DelegateCommand(NextPageAction);

            _lastPageCommand = new DelegateCommand(LastPageAction);
        }

        private void FirstPageAction()
        {
            CurrentPage = 1;

            var result = _source.Take(_pageSize).ToList();

            _fakeSoruce.Clear();

            _fakeSoruce.AddRange(result);
        }

        private void PreviousPageAction()
        {
            if(CurrentPage == 1)
            {
                return;
            }

            List<FakeDatabase> result = new List<FakeDatabase>();

            if(CurrentPage == 2)
            {
                result = _source.Take(_pageSize).ToList();
            }
            else
            {
                result = _source.Skip((CurrentPage - 2) * _pageSize).Take(_pageSize).ToList();
            }

            _fakeSoruce.Clear();

            _fakeSoruce.AddRange(result);

            CurrentPage--;
        }

        private void NextPageAction()
        {
            if(CurrentPage == _totalPage)
            {
                return;
            }

            List<FakeDatabase> result = new List<FakeDatabase>();

            result = _source.Skip(CurrentPage * _pageSize).Take(_pageSize).ToList();

            _fakeSoruce.Clear();

            _fakeSoruce.AddRange(result);

            CurrentPage++;
        }

        private void LastPageAction()
        {
            CurrentPage = TotalPage;

            int skipCount = (_totalPage - 1) * _pageSize;
            int takeCount = _source.Count - skipCount;

            var result = _source.Skip(skipCount).Take(takeCount).ToList();

            _fakeSoruce.Clear();

            _fakeSoruce.AddRange(result);
        }
    }

 

其它补充代码: 

DelegateCommand

public class DelegateCommand<T> : ICommand
    {
        private static bool CanExecute(T parameter)
        {
            return true;
        }

        private readonly Action<T> _execute;

        private Func<T, bool> _canExecute;

        public DelegateCommand(Action<T> execute, Func<T, bool> canExecute = null)
        {
            if (execute == null)
            {
                throw new ArgumentNullException("execute is null.");
            }

            _execute = execute;
            _canExecute = canExecute ?? CanExecute;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute(TranslateParameter(parameter));
        }

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (_canExecute != null)
                {
                    CommandManager.RequerySuggested += value;
                }
            }

            remove
            {
                if (_canExecute != null)
                {
                    CommandManager.RequerySuggested -= value;
                }
            }
        }

        public void Execute(object parameter)
        {
            _execute(TranslateParameter(parameter));
        }

        private T TranslateParameter(object parameter)
        {
            T value = default(T);
            if (parameter != null && typeof(T).IsEnum)
                value = (T)Enum.Parse(typeof(T), (string)parameter);
            else
                value = (T)parameter;
            return value;
        }
    }

    public class DelegateCommand : DelegateCommand<object>
    {
        public DelegateCommand(Action execute,Func<bool> canExecute = null)
            : base(obj => execute(),
                 (canExecute == null ? null : new Func<object, bool>(obj => canExecute())))
        {

        }
    }

 

FakeDatabase

  public class FakeDatabase
    {
        public int Id { get; set; }

        public string ItemName { get; set; }

        public List<FakeDatabase> GenerateFakeSource()
        {
            List<FakeDatabase> source = new List<FakeDatabase>(); 

            for (int i = 0; i < 1000; i++)
            {
                FakeDatabase item = new FakeDatabase()
                {
                    Id = i,
                    ItemName = "Item" + i.ToString()
                };

                source.Add(item);
            }

            return source;
        }

        public FakeDatabase()
        {
            
        }
    }

 

Extension

   public static class Extension
    {
        public static void AddRange<T>(this ObservableCollection<T> collection, IEnumerable<T> items)
        {
            items.ToList().ForEach(collection.Add);
        }
    }

 

ViewModel

  public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

  

 

 

本文中的代码转自于博客:https://www.cnblogs.com/yang-fei/p/4724899.html

 

ViewModel

posted @ 2021-11-02 15:48  安静点--  阅读(3588)  评论(1编辑  收藏  举报