原文:wpf控件开发基础(5) -依赖属性实践

知识回顾

接上篇,回顾这三篇讲了什么东西

首先说明了属性的现存问题,然后介绍了依赖属性的基本用法及其解决方案,由于依赖属性以静态属性的方式存在,进而又介绍了可重写的属性元数据的使用.这是以上三篇所说明的问题.当然依赖属性的特性依然没有说完整.这两天也一直在想依赖属性,然后就是头疼,呵呵.由于WPF的依赖属性系统与整体功能都有关联,所以接下来等讲到某个特性的时候然后再来讲依赖属性.这篇我们来个简单的实践,增加点乐趣.

定义RadioButtonList和CheckBoxList

WPF内置没有这两个控件,但实际开发时,用到的会比较多.下面我们一起来创建这两个控件.

  1. 明确控件需求
  2. 定义依赖属性
  3. 重写默认样式属性元数据
  4. 用xaml定义控件样式

一.明确控件需求

控件功能如下:

  1. 可以垂直,水平排列
  2. 可以分行,列
  3. 为子项设置Margin

二.定义依赖属性

为避免重复定义属性,为两个控件定义公共类ListControl,从ListBox继承

然后定义依赖属性

  1. namespace WPF.Controls
  2. {
  3. /// <summary>
  4. /// this is a base class for CheckBoxList and RadioButtonList
  5. /// this class define some common property
  6. /// </summary>
  7. public abstract class ListControl : ListBox
  8. {
  9.  
  10. #region Orientation
  11.  
  12. /// <summary>
  13. /// Gets or sets a value that indicates the dimension by which child elements are stacked.
  14. /// This is a dependency property.
  15. /// </summary>
  16. public Orientation Orientation
  17. {
  18. get { return (Orientation)GetValue(OrientationProperty); }
  19. set { SetValue(OrientationProperty, value); }
  20. }
  21.  
  22. public static readonly DependencyProperty OrientationProperty =
  23. DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ListControl),
  24. new UIPropertyMetadata(Orientation.Vertical, new PropertyChangedCallback(OrientationChangedCallback)));
  25.  
  26. public static void OrientationChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  27. {
  28. ListControl control = d as ListControl;
  29. if (control.Orientation == Orientation.Horizontal)
  30. {
  31. control.Columns = 0;
  32. control.Rows = 1;
  33. }
  34. else if (control.Orientation == Orientation.Vertical)
  35. {
  36. control.Rows = 0;
  37. control.Columns = 1;
  38. }
  39. }
  40.  
  41. #endregion
  42.  
  43. #region Columns
  44.  
  45. /// <summary>
  46. /// Get or set a value that indicates which Columns list item should appear in.
  47. /// This is a dependency property.
  48. /// </summary>
  49. public int Columns
  50. {
  51. get { return (int)GetValue(ColumnsProperty); }
  52. set { SetValue(ColumnsProperty, value); }
  53. }
  54.  
  55. public static readonly DependencyProperty ColumnsProperty =
  56. DependencyProperty.Register("Columns", typeof(int), typeof(ListControl), new UIPropertyMetadata(1));
  57.  
  58. #endregion
  59.  
  60. #region Rows
  61.  
  62. /// <summary>
  63. /// Get or set a value that indicates which Rows list item should appear in.
  64. /// This is a dependency property.
  65. /// </summary>
  66. public int Rows
  67. {
  68. get { return (int)GetValue(RowsProperty); }
  69. set { SetValue(RowsProperty, value); }
  70. }
  71.  
  72. public static readonly DependencyProperty RowsProperty =
  73. DependencyProperty.Register("Rows", typeof(int), typeof(ListControl), new UIPropertyMetadata(0));
  74.  
  75. #endregion
  76.  
  77. public Thickness SubMargin
  78. {
  79. get { return (Thickness)GetValue(SubMarginProperty); }
  80. set { SetValue(SubMarginProperty, value); }
  81. }
  82.  
  83. public static readonly DependencyProperty SubMarginProperty =
  84. DependencyProperty.Register("SubMargin", typeof(Thickness), typeof(ListControl),
  85. new UIPropertyMetadata(new Thickness(2,2,2,0)));
  86.  
  87. }
  88. }

以上依赖属性定义的非常简单,之所以定义成依赖属性是因为可以进行属性绑定操作.

三.重写默认样式属性元数据

  1. /// <summary>
  2. /// Represents a control that a user can choose one from list options in a group radiobutton
  3. /// </summary>
  4. public class RadioButtonList : ListControl
  5. {
  6. static RadioButtonList()
  7. {
  8. DefaultStyleKeyProperty.OverrideMetadata(typeof(RadioButtonList)
  9. , new FrameworkPropertyMetadata(typeof(RadioButtonList)));
  10. }
  11. }
  12.  
  13. /// <summary>
  14. /// Contains a list of selectable CheckBox items
  15. /// Represents a control that a user can choose from a list options in a group of CheckBox
  16. /// </summary>
  17. public class CheckBoxList : ListControl
  18. {
  19. static CheckBoxList()
  20. {
  21. DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckBoxList)
  22. , new FrameworkPropertyMetadata(typeof(CheckBoxList)));
  23. }
  24. }

四.用xaml定义控件样式

默认项目中会有一个Generic.xaml文件,我们要把样式定义在此文件中

控件样式定义

(1)ListControl

  1. <Style TargetType="{x:Type local:ListControl}" BasedOn="{StaticResource {x:Type ListBox}}">
  2. <Setter Property="ItemsPanel">
  3. <Setter.Value>
  4. <ItemsPanelTemplate>
  5. <UniformGrid HorizontalAlignment="Left" VerticalAlignment="Top"
  6. Rows="{Binding Path=Rows,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:ListControl}}}"
  7. Columns="{Binding Path=Columns,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:ListControl}}}"></UniformGrid>
  8. </ItemsPanelTemplate>
  9. </Setter.Value>
  10. </Setter>
  11. <Setter Property="BorderThickness" Value="0" />
  12. <Setter Property="Background" Value="Transparent" />
  13. </Style>

(2)RadioButtonList

  1. <Style TargetType="{x:Type local:RadioButtonList}" BasedOn="{StaticResource {x:Type local:ListControl}}">
  2. <Style.Resources>
  3. <Style TargetType="ListBoxItem">
  4. <Setter Property="Margin" Value="2, 2, 2, 0" />
  5. <Setter Property="Template">
  6. <Setter.Value>
  7. <ControlTemplate TargetType="ListBoxItem">
  8. <RadioButton
  9. Margin="{Binding Path=SubMargin,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:RadioButtonList}}}"
  10. IsChecked="{Binding IsSelected, RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}">
  11. <RadioButton.Content>
  12. <ContentPresenter/>
  13. </RadioButton.Content>
  14. </RadioButton>
  15. </ControlTemplate>
  16. </Setter.Value>
  17. </Setter>
  18. </Style>
  19. </Style.Resources>
  20. </Style>

(3)CheckBoxList

  1. <Style TargetType="{x:Type local:CheckBoxList}" BasedOn="{StaticResource {x:Type local:ListControl}}">
  2. <Setter Property="SelectionMode" Value="Multiple"></Setter>
  3. <Style.Resources>
  4. <Style TargetType="ListBoxItem">
  5. <Setter Property="Margin" Value="2, 2, 2, 0" />
  6. <Setter Property="Template">
  7. <Setter.Value>
  8. <ControlTemplate TargetType="ListBoxItem">
  9. <CheckBox
  10. Margin="{Binding Path=SubMargin,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:RadioButtonList}}}"
  11. IsChecked="{Binding IsSelected, RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}">
  12. <CheckBox.Content>
  13. <ContentPresenter/>
  14. </CheckBox.Content>
  15. </CheckBox>
  16. </ControlTemplate>
  17. </Setter.Value>
  18. </Setter>
  19. </Style>
  20. </Style.Resources>
  21. </Style>

OK,到这里就完事了.我们发现我们并不需要写多少代码,就可以实现一个控件.而且RadioButtonList和CheckBoxList几乎没有代码,仅仅只是重写了样式而已,这也是WPF定义控件的基本概念,一些变的都是如此简单.

Demo下载

wpf控件开发基础(5) -依赖属性实践的更多相关文章

  1. wpf控件开发基础(3) -属性系统(2)

    原文:wpf控件开发基础(3) -属性系统(2) 上篇说明了属性存在的一系列问题. 属性默认值,可以保证属性的有效性. 属性验证有效性,可以对输入的属性进行校验 属性强制回调, 即不管属性有无发生变化 ...

  2. wpf控件开发基础(4) -属性系统(3)

    原文:wpf控件开发基础(4) -属性系统(3) 知识回顾 接上篇,上篇我们真正接触到了依赖属性的用法,以及依赖属性的属性元数据的用法,并且也实实在在地解决了之前第二篇提到的一系列问题.来回顾一下 属 ...

  3. wpf控件开发基础(2) -属性系统(1)

    原文:wpf控件开发基础(2) -属性系统(1) 距离上篇写的时间有1年多了.wpf太大,写的东西实在太多,我将依然围绕着自定义控件来展开与其相关的技术点. 也欢迎大家参与讨论.这篇我们将要讨论的是W ...

  4. wpf控件开发基础

    wpf控件开发基础(3) -属性系统(2) http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661370.html 这个有必要看看 wpf ...

  5. asp.net控件开发基础(1)(转)原文更多内容

    asp.net本身提供了很多控件,提供给我们这些比较懒惰的人使用,我认为控件的作用就在此,因为我们不想重复工作,所以要创建它,这个本身便是一个需求的关系,所以学习控件开发很有意思. wrox网站上有本 ...

  6. WPF控件开发(2) 自动完成(AutoComplete)-1

    自动完成功能使用范围很广,多以TextBox或ComboBox的形式出现,在输入的同时给予候选词,候选词一般有两种方式获取. 一种类似Baidu,Google,Bing之类的搜索引擎所用的直接给予前十 ...

  7. 跟我一起学WPF(2):WPF控件基础

    WPF控件简介 通过上一篇XAML语言的介绍,我们知道,XAML是一个树形结构,同样,WPF控件作为构成整个XAML树的一部分,也是一个树形结构.我们看一个简单的例子. <Button.Cont ...

  8. WinForm控件开发总结目录

    WinForm控件开发总结(一)------开篇 WinForm控件开发总结(二)------使用和调试自定义控件 WinForm控件开发总结(三)------认识WinForm控件常用的Attrib ...

  9. WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性

    原文:WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性 如果你要自定义一个图片按钮控件,那么如何在主窗体绑定这个控件上图片的Source呢? ...

随机推荐

  1. Ansible 管理服务和软件

    [root@Ansible ~]# ansible RAC -m yum -a 'name=iscsi-initiator-utils state=installed' RAC_Node1 | suc ...

  2. Hibernate与代理模式

    代理模式:当须要调用某个对象的时候.不须要关心拿到的是不是一定是这个对象,它须要的是,我拿到的这个对象能够完毕我想要让它完毕的任务就可以,也就是说.这时调用方能够拿到一个代理的一个对象,这个对象能够调 ...

  3. ZOJ 1914 Arctic Network (POJ 2349 UVA 10369) MST

    ZOJhttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1914 POJhttp://poj.org/problem?id=23 ...

  4. POJ 3641 Oulipo KMP 水题

    http://poj.org/problem?id=3461 直接KMP就好.水题 #include<cstdio> #include<cstring> const int M ...

  5. Socket编程模型之完毕port模型

    转载请注明来源:viewmode=contents">http://blog.csdn.net/caoshiying?viewmode=contents 一.回想重叠IO模型 用完毕例 ...

  6. github-vimium-compile-crx

    chrome-62.x版本上安装vimium 1.61.1 https://blog.csdn.net/ZHUJIANWEILI4/article/details/78385346

  7. iOS开发webView的使用二

    #import "ViewController.h" @interface ViewController ()<UIWebViewDelegate> @property ...

  8. 【9201】&&【a201】明明的随机数

    Time Limit: 10 second Memory Limit: 2 MB 问题描述 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整 ...

  9. runtimeException也是能够捕获的

    如题, 运行结果: bbb abcdef @Test public void testRuntimeException() { ; try { aaa333(); } catch (Exception ...

  10. Windows Phone 8.1 控件

    如果你已经开始了 Windows Phone 8.1 的学习,就会发现许多在 8.0 下的控件在 8.1 中都发生了变化,以下就谈谈几个 8.1 下的新控件以及与 8.0 控件的改变. 1. Text ...