欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【WPF实用教程4】自定义控件的属性和事件

程序员文章站 2022-05-29 18:16:19
...

【WPF实用教程4】自定义控件的属性和事件

(玖零_WPF技术交流)QQ群:912098291

1. 前言:

上一篇文章中,我演示了一个带有水印的具有清除按钮的输入框,那么这一节我准备再给输入框增加一个搜索按钮以及增加一些自定义属性和事件。本篇的工程基于【WPF实用教程3】最后的工程修改。

2. 背景知识

在上一篇文章中,我们已经为ClearTextBox增加了一个WaterMark的属性,如下图:

【WPF实用教程4】自定义控件的属性和事件

从上图中我们可以看到一些词比如Category、DependencyProperty、PropertyMeradata。其中:

  • Category装饰语句是用来对属性进行分类,[]的内容最终呈现的效果是在VS控件的属性TAB页内,如下图所示:

【WPF实用教程4】自定义控件的属性和事件

  • DependencyProperty叫做“依赖属性”,是WPF框架基于微软的“属性”这个概念推进衍生出的一个新的概念。简而言之,依赖属性是一种可以自己没有值,并能通过使用Binding从数据源获得值(依赖在别人身上)的属性,其中拥有依赖属性的对象被称为“依赖对象(Dependency Object)”。与传统的CLR属性相比,依赖属性有很多新颖之处,其中包括:节省实例对内存的开销、属性值可以通过Binding依赖在其他对象。---语句源自刘铁猛老师

举个简单的例子,以共享单车来说,我(依赖对象)拥有一辆交通工具(依赖属性),当我需要用到交通工具的时候,我选择(Binding)了一辆小黄车(数据源),这样我节省了买交通工具的钱(节省了内存开销)。PS:之前有人给我杠“那你还付小黄车的钱和押金了呢”,我回复“我去你个鬼!”

 

注意:使用DependencyProperty声明的成员变量所引用的实例并非使用new操作符得到,而是使用DependencyProperty.Register方法创建。

 

  • 关于更详细的解释,我这里暂时不解释,这部分概念很重要,需要很长的篇幅解释,我后面会单独拿出来一篇文章解释。这也是我学习的方法,先会用,再探究原理。我们现在只需要知道在自定义控件里声明一个字段的大致格式就行了。

3. 工程

3.1 为控件ClearText的清除图标添加填充色和大小两个字段

【WPF实用教程4】自定义控件的属性和事件

在不同的应用场景下,有时我们会对清除图标的背景色和大小需要修改,而我目前在工程中是直接写成了固定值,这样是不好的,下面我们在ClearTextBox.cs中增加以下内容:

#region 清除图标 属性
[Category("Extend Properties")]
public Brush ClearIconFill
{
  get { return (Brush)GetValue(ClearIconFillProperty); }
  set { SetValue(ClearIconFillProperty, value); }
}

public static readonly DependencyProperty ClearIconFillProperty =
            DependencyProperty.Register("ClearIconFill", typeof(Brush), typeof(ClearTextBox), new PropertyMetadata(Brushes.Gray));

[Category("Extend Properties")]
public Double ClearIconFontSize
{
  get { return (Double)GetValue(ClearIconFontSizeProperty); }
  set { SetValue(ClearIconFontSizeProperty, value); }
}

public static readonly DependencyProperty ClearIconFontSizeProperty =
            DependencyProperty.Register("ClearIconFontSize", typeof(Double), typeof(ClearTextBox));

#endregion

修改ClearTextBox\Themes.xaml中的清除按钮内容为下图:

【WPF实用教程4】自定义控件的属性和事件

然后修改项目MicroUI.Wpf.Samples\MainWindow.xaml中ClearTextBox控件如下:

【WPF实用教程4】自定义控件的属性和事件

重新生成解决方案,运行如下图:

【WPF实用教程4】自定义控件的属性和事件

可以看到我们自定义属性已经生效了。

3.2 添加搜索图标

我们再来给该控件加个搜索按钮以及搜索事件。

首先在Style\MicroIcon.xaml中添加搜索图标样式

<Style x:Key="MicroBtnIcon_Search" TargetType="{x:Type Button}" BasedOn="{StaticResource MicroBtnIcon}" >
        <Setter Property="Content" Value="&#xe688;" />
</Style>

【WPF实用教程4】自定义控件的属性和事件

其中的图标的Unicode值用你自己的图标也可以。

【WPF实用教程4】自定义控件的属性和事件

然后修改ClearText\Themes.xaml代码,添加箭头所指的内容:

【WPF实用教程4】自定义控件的属性和事件

同时增加以下内容:


<Button x:Name="PART_SearchButtonHost" Grid.Column="3" 
  Padding="2,0"
  Style="{StaticResource MicroBtnIcon_Search}"  
  FontSize="20"
  />

【WPF实用教程4】自定义控件的属性和事件

重新生成解决方案,运行,如下图:

【WPF实用教程4】自定义控件的属性和事件

可以看到搜索按钮也有了。下面我按照上一节提到的方法,搜索按钮添加填充色和大小两个字段:

#region 搜索图标 属性
[Category("Extend Properties")]
public Brush SaerchIconFill
{
  get { return (Brush)GetValue(SaerchIconFillProperty); }
  set { SetValue(SaerchIconFillProperty, value); }
}

public static readonly DependencyProperty SaerchIconFillProperty =
  DependencyProperty.Register("SaerchIconFill", typeof(Brush), typeof(ClearTextBox), new PropertyMetadata(Brushes.Gray));

[Category("Extend Properties")]
public Double SaerchIconFontSize
{
   get { return (Double)GetValue(SaerchIconFontSizeProperty); }
   set { SetValue(SaerchIconFontSizeProperty, value); }
}

public static readonly DependencyProperty SaerchIconFontSizeProperty =
  DependencyProperty.Register("SaerchIconFontSize", typeof(Double), typeof(ClearTextBox));

#endregion

修改ClearTextBox\Themes.xaml中的搜索按钮内容如下:

【WPF实用教程4】自定义控件的属性和事件

修改MicroUI.Wpf.Samples中的MainWindow.xaml的ClearTextBox内容如下:

【WPF实用教程4】自定义控件的属性和事件

重新生成解决方案,运行:

【WPF实用教程4】自定义控件的属性和事件

此时的样式还是可以的。

3.3 添加自定义事件

接下来,我们给搜索按钮添加一个自定义事件,使得用户可以订阅该点击事件从而执行搜索逻辑。

在ClearTextBox.cs中添加下图箭头所指的两处:

【WPF实用教程4】自定义控件的属性和事件

 

同样的在该文件中添加:

#region 自定义按钮事件
        
[Category("Behavior")]
public static readonly RoutedEvent OnSearchEvent =
  EventManager.RegisterRoutedEvent(
  "OnSearch",
  RoutingStrategy.Bubble,
  typeof(RoutedEventHandler),
  typeof(ClearTextBox));
public event RoutedEventHandler OnSearch
{
  add { AddHandler(OnSearchEvent, value); }
  remove { RemoveHandler(OnSearchEvent, value); }
}
#endregion

【WPF实用教程4】自定义控件的属性和事件

继续添加事件处理方法:


//搜索按钮处理方法
private void HandleOnSearchClick(object sender, RoutedEventArgs e)
{
  this.RaiseEvent(new RoutedEventArgs(ClearTextBox.OnSearchEvent, this));
}

【WPF实用教程4】自定义控件的属性和事件

在OnApplyTemplate()方法中添加以下语句:


if (searchButtonHost != null)
{
  searchButtonHost.Click -= HandleOnSearchClick;
}
searchButtonHost = GetTemplateChild("PART_SearchButtonHost") as ButtonBase;
if (searchButtonHost != null)
{
  searchButtonHost.Click += HandleOnSearchClick;
}

【WPF实用教程4】自定义控件的属性和事件

此时自定义控件的内容添加完毕,接下来去MainWindow.xaml中添加订阅事件:

【WPF实用教程4】自定义控件的属性和事件

MainWindow.xaml.cs中的事件处理方法为:

【WPF实用教程4】自定义控件的属性和事件

重新生成解决方案,运行:

【WPF实用教程4】自定义控件的属性和事件

可以看到订阅的事件被触发。

3.4 小节

通过本篇可以学到的知识点:

  • 自定义控件添加依赖属性

  • 自定义控件添加自定义事件

4. 代码下载

公众号后台关键词回复"WPF实用教程源码"

/////////////////////////////////////////////////////////////////////////////////////////

** 原创文章,转载请附该部分声明

** 公众号:玖零大壮

** 作者微信:wensong2048

/////////////////////////////////////////////////////////////////////////////////////////