ToB企服应用市场:ToB评测及商务社交产业平台

标题: WPF开发快速入门【4】自定义控件与用户控件 [打印本页]

作者: 欢乐狗    时间: 2022-9-16 17:19
标题: WPF开发快速入门【4】自定义控件与用户控件
概述
本文描述WPF的自定义控件和用户控件。
 
自定义控件
前面文章介绍了WPF的ControlTemplate,当我们对系统控件自带的样式不太满意时,我们可以通过控件模板自定义用户的样式,以Button为例,我们可以设计一个圆形的按钮,并通过触发器控制一些动态效果。在使用控件模板时,我们通过TemplateBinding来引用控件的一些属性,这个属性的范围仅限于Button本身所拥有的属性。
如果我想设计一款带图片的按钮,通过控件模板就实现不了了,因为这个图片按钮的控件应该具备一个类似Image这样的属性,但Button控件没有这个属性,所以就实现不了我们想要的功能了。
这时候可以使用自定义控件来解决问题。
我们新建一个ImageButton的自定义控件,系统自动生成一个类文件和一个样式文件: 
  1. //ImageButton.cs
  2.     public class ImageButton : Control
  3.     {
  4.         static ImageButton()
  5.         {
  6.             DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton)));
  7.         }
  8.     }
  9. //Generic.xaml
  10.    
复制代码
 首先我们需要把ImageButton 父类修改为Button,表示这个控件功能继承于Button,然后我们为这个类增加一个Image属性
  1.         public ImageSource Image
  2.         {
  3.             get { return (ImageSource)GetValue(ImageProperty); }
  4.             set { SetValue(ImageProperty, value); }
  5.         }
  6.         public static readonly DependencyProperty ImageProperty =
  7.             DependencyProperty.Register("Image", typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(null));
复制代码
此时,这个控件的后台代码就完成了。
然后我们再仔细看看Generic.xaml中对于local:ImageButton这个控件的样式描述,这不就是修改它的控件模板吗?不过此时,除了Button的现有属性,我们还多了一个Image属性可以使用。
下面我们完善一下这个控件模板的描述。
  1.    
复制代码
 这样一个自定义控件就做好了。
 
 和控件模板一样,我们还是可以通过Trigger控制控件的一些动态效果:
  1.    
复制代码
  
用户控件
用户控件比较简单,就是通过一些现有控件的组合,形成一个可以通用的控件。例如:通过组合一个加号的图片、一个减号的图片、一个文本框,我们可以组合一个NumericUpDown控件。 
  1. <UserControl x:Class="LearnWPF.Controls.NumericUpDown">   
  2.     <Border BorderThickness="1" BorderBrush="LightGray" >
  3.         <Grid >
  4.             <Grid.ColumnDefinitions>
  5.                 <ColumnDefinition Width="30"/>
  6.                 <ColumnDefinition Width="50"/>
  7.                 <ColumnDefinition Width="30"/>
  8.             </Grid.ColumnDefinitions>
  9.             <Border Grid.Column="0" >
  10.                 <Image Source="Images/Subtract.png" Margin="4"
  11.                        MouseDown="ButtonSubtract_Click">
  12.                 </Image>
  13.             </Border>
  14.             <TextBox x:Name="txtValue" Text="1.220"                     
  15.                      TextChanged="txtValue_TextChanged"/>
  16.             <Border Grid.Column="2">
  17.                 <Image Source="Images/Add.png" Margin="4"
  18.                        MouseDown="ButtonAdd_Click">
  19.                 </Image>
  20.             </Border>
  21.         </Grid>
  22.     </Border>
  23. </UserControl>
复制代码
 我们可以给控件增加一个Value的属性,然后当用户点击图片按钮时,我们修改Value的值即可。
  1.         private void ButtonAdd_Click(object sender, RoutedEventArgs e)
  2.         {
  3.             Value += Increment;           
  4.         }
  5.         private void ButtonSubtract_Click(object sender, RoutedEventArgs e)
  6.         {
  7.             Value -= Increment;            
  8.         }
复制代码
 此时,这个用户控件就开发完成了。但它不支持MVVM模式,因为Value属性不是依赖属性,我们需要把Value属性定义为依赖属性:
  1.         public decimal Value
  2.         {
  3.             get { return (decimal)GetValue(ValueProperty); }
  4.             set { SetValue(ValueProperty, value); }
  5.         }
  6.         public static readonly DependencyProperty ValueProperty =
  7.                DependencyProperty.Register("Value", typeof(decimal), typeof(NumericUpDown), new UIPropertyMetadata(new decimal(), ValuePropertyChanged));
  8.         private static void ValuePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs arg)
  9.         {
  10.             NumericUpDown control = obj as NumericUpDown;
  11.             decimal Data = (decimal)arg.NewValue;
  12.             control.txtValue.Text = Math.Round(Data, control.DecimalPlaces).ToString();
  13.         }
复制代码
 此时Value属性就支持MVVM,而且支持双向Binding模式
[code][/code] 由于 Minimum和Maximum不是依赖属性,只能直接幅值,不能绑定。
 
自绘的用户控件
有时候我们需要做一些很奇怪的控件,如下:

这个也是通过用户控件实现。我的经验是:在用户控件里放一个Image控件,缩放模式设置为Fill,然后在后台画个图并复值给Image控件即可。
在绘图时,由于用户会调整控件尺寸,所以绘图控件的定位是比较麻烦的,我们可以画一个指定尺寸的图,然后让Image来处理缩放,这就比较简单了。
设计代码:
[code]




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4