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

知识回顾

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

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

定义RadioButtonList和CheckBoxList

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

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

一.明确控件需求

控件功能如下:

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

二.定义依赖属性

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

然后定义依赖属性

namespace WPF.Controls
{
/// <summary>
/// this is a base class for CheckBoxList and RadioButtonList
/// this class define some common property
/// </summary>
public abstract class ListControl : ListBox
{ #region Orientation /// <summary>
/// Gets or sets a value that indicates the dimension by which child elements are stacked.
/// This is a dependency property.
/// </summary>
public Orientation Orientation
{
get { return (Orientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
} public static readonly DependencyProperty OrientationProperty =
DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ListControl),
new UIPropertyMetadata(Orientation.Vertical, new PropertyChangedCallback(OrientationChangedCallback))); public static void OrientationChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ListControl control = d as ListControl;
if (control.Orientation == Orientation.Horizontal)
{
control.Columns = 0;
control.Rows = 1;
}
else if (control.Orientation == Orientation.Vertical)
{
control.Rows = 0;
control.Columns = 1;
}
} #endregion #region Columns /// <summary>
/// Get or set a value that indicates which Columns list item should appear in.
/// This is a dependency property.
/// </summary>
public int Columns
{
get { return (int)GetValue(ColumnsProperty); }
set { SetValue(ColumnsProperty, value); }
} public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.Register("Columns", typeof(int), typeof(ListControl), new UIPropertyMetadata(1)); #endregion #region Rows /// <summary>
/// Get or set a value that indicates which Rows list item should appear in.
/// This is a dependency property.
/// </summary>
public int Rows
{
get { return (int)GetValue(RowsProperty); }
set { SetValue(RowsProperty, value); }
} public static readonly DependencyProperty RowsProperty =
DependencyProperty.Register("Rows", typeof(int), typeof(ListControl), new UIPropertyMetadata(0)); #endregion public Thickness SubMargin
{
get { return (Thickness)GetValue(SubMarginProperty); }
set { SetValue(SubMarginProperty, value); }
} public static readonly DependencyProperty SubMarginProperty =
DependencyProperty.Register("SubMargin", typeof(Thickness), typeof(ListControl),
new UIPropertyMetadata(new Thickness(2,2,2,0))); }
}

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

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

/// <summary>
/// Represents a control that a user can choose one from list options in a group radiobutton
/// </summary>
public class RadioButtonList : ListControl
{
static RadioButtonList()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(RadioButtonList)
, new FrameworkPropertyMetadata(typeof(RadioButtonList)));
}
} /// <summary>
/// Contains a list of selectable CheckBox items
/// Represents a control that a user can choose from a list options in a group of CheckBox
/// </summary>
public class CheckBoxList : ListControl
{
static CheckBoxList()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckBoxList)
, new FrameworkPropertyMetadata(typeof(CheckBoxList)));
}
}

四.用xaml定义控件样式

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

控件样式定义

(1)ListControl

<Style TargetType="{x:Type local:ListControl}" BasedOn="{StaticResource {x:Type ListBox}}">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<UniformGrid HorizontalAlignment="Left" VerticalAlignment="Top"
Rows="{Binding Path=Rows,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:ListControl}}}"
Columns="{Binding Path=Columns,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:ListControl}}}"></UniformGrid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
</Style>

(2)RadioButtonList

<Style TargetType="{x:Type local:RadioButtonList}" BasedOn="{StaticResource {x:Type local:ListControl}}">
<Style.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Margin" Value="2, 2, 2, 0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<RadioButton
Margin="{Binding Path=SubMargin,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:RadioButtonList}}}"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}">
<RadioButton.Content>
<ContentPresenter/>
</RadioButton.Content>
</RadioButton>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
</Style>

(3)CheckBoxList

<Style TargetType="{x:Type local:CheckBoxList}" BasedOn="{StaticResource {x:Type local:ListControl}}">
<Setter Property="SelectionMode" Value="Multiple"></Setter>
<Style.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Margin" Value="2, 2, 2, 0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<CheckBox
Margin="{Binding Path=SubMargin,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:RadioButtonList}}}"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}">
<CheckBox.Content>
<ContentPresenter/>
</CheckBox.Content>
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
</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. thinkphp3.1课程 1-2 thinkphp中入口文件的实质是什么

    thinkphp3.1课程 1-2 thinkphp中入口文件的实质是什么 一.总结 一句话总结:在thinkphp中,我们访问的始终是入口文件,并没有主动去访问任何一个其他文件,只不过在入口文件体内 ...

  2. bootstrap 时间控件带(时分秒)选择器(需要修改才能显示,请按照参数说明后面的步骤进行修改)

    1.控件下载地址:http://www.bootcss.com/p/bootstrap-datetimepicker/index.htm,参数设置说明也在这个链接下面: 2.具体参数说明(复制原链接) ...

  3. Microsoft Bot Framework 链接至微信公共号

    如何将 Microsoft Bot Framework 链接至微信公共号   说到 Microsoft Bot Framework 其实微软发布了已经有一段时间了,有很多朋友可能还不太了解,微软Bot ...

  4. ORA-00119: invalid specification for system parameter LOCAL_LISTENER;

    错误提示内容及上下文环境: SQL> grant sysdba to weng;grant sysdba to weng*第 1 行出现错误:ORA-01034: ORACLE not avai ...

  5. php 微信支付企业付款

    1.所需参数 字段名 变量名 必填 示例值 类型 描述 公众账号appid mch_appid 是 wx8888888888888888 String 公众号的appId 商户号 mchid 是 19 ...

  6. 【u117】队列安排

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 一个学校里老师要将班上N个同学排成一列,同学被编号为1-N,他采取如下的方法: 1. 先将1号同学安排 ...

  7. 新版Sublime text3注册码被移除的解决办法

    Sublime Text是风靡世界的文本编辑器,支持多种编程语言,启动时间短,打开文件速度快,插件丰富,让很多程序员爱不释手.但是,对于未注册的Sublime Text, 经常在保存的时候会弹出一个烦 ...

  8. Qt 学习: 视图选择 (QItemSelectionModel)

    博主QQ:1356438802 选择是视图中经常使用的一个操作.在列表.树或者表格中,通过鼠标点击能够选中某一项,被选中项会变成高亮或者反色.在 Qt 中,选择也是使用了一种模型.在 model/vi ...

  9. 【最小树形图(奇怪的kruskal)】【SCOI 2012】【bzoj 2753】滑雪与时间胶囊

    2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec Memory Limit: 128 MB Submit: 1621 Solved: 570 Description ...

  10. Cocos2D-html5 公布游戏js编译为jsc

    搞了老半天.这么回事啊.工具都在tools中. jsb模式下是通过打包spidermonkey来执行JS代码的. JS文件都在assets目录中.我们都知道assets目录.打包后的结果,将apk包解 ...