zoukankan      html  css  js  c++  java
  • wpf控件开发基础(5) 依赖属性实践

    知识回顾

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

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

    定义RadioButtonList和CheckBoxList

    image image

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

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

    一.明确控件需求

    控件功能如下:

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

    二.定义依赖属性

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

    image

    然后定义依赖属性

    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文件,我们要把样式定义在此文件中

    image

    控件样式定义

    (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下载

  • 相关阅读:
    windows2008R2下iis7.5中的url重写(urlrewrite)
    C#操作IIS程序池及站点的创建配置实现代码
    C#获取IP及MAC地址 方法
    linq list select用法注意事项
    c#写windows服务 小demo
    C#创建Windows Service(Windows 服务)基础教程
    C# 编写Windows Service(windows服务程序)
    C#中DataTable中的Compute方法使用收集
    SQL Delta实用案例介绍,很好的东西,帮了我不少忙
    Linq中demo,用力看看吧
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/1662562.html
Copyright © 2011-2022 走看看