﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-Clingingboy</title><link>http://www.cnblogs.com/Clingingboy/</link><description /><language>zh-cn</language><lastBuildDate>Wed, 10 Feb 2010 04:22:57 GMT</lastBuildDate><pubDate>Wed, 10 Feb 2010 04:22:57 GMT</pubDate><ttl>60</ttl><item><title>wpf控件开发基础(5) -依赖属性实践</title><link>http://www.cnblogs.com/Clingingboy/archive/2010/02/03/1662562.html</link><dc:creator>Clingingboy</dc:creator><author>Clingingboy</author><pubDate>Wed, 03 Feb 2010 04:36:00 GMT</pubDate><guid>http://www.cnblogs.com/Clingingboy/archive/2010/02/03/1662562.html</guid><description><![CDATA[<p>阅读: 890 评论: 4 作者: <a href="http://www.cnblogs.com/Clingingboy/" target="_blank">Clingingboy</a> 发表于 2010-02-03 12:36 <a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/03/1662562.html" target="_blank">原文链接</a></p><h2>知识回顾</h2> <p><a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/02/1661842.html">接上篇</a>,回顾这三篇讲了什么东西</p> <p>首先说明了属性的<strong>现存问题</strong>,然后介绍了依赖属性的<strong>基本用法</strong>及其解决方案,由于依赖属性以静态属性的方式存在,进而又介绍了<strong>可重写的属性元数据</strong>的使用.这是以上三篇所说明的问题.当然依赖属性的特性依然没有说完整.这两天也一直在想依赖属性,然后就是头疼,呵呵.由于WPF的依赖属性系统与整体功能都有关联,所以接下来等讲到某个特性的时候然后再来讲依赖属性.这篇我们来个简单的实践,增加点乐趣.</p> <h2>定义RadioButtonList和CheckBoxList</h2> <p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf54_D5A8/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf54_D5A8/image_thumb_1.png" width="341" height="247"></a> <a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf54_D5A8/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf54_D5A8/image_thumb.png" width="356" height="302"></a> </p> <p>WPF内置没有这两个控件,但实际开发时,用到的会比较多.下面我们一起来创建这两个控件.</p> <ol> <li><strong>明确控件需求</strong></li> <li><strong>定义依赖属性</strong></li> <li><strong>重写默认样式属性元数据</strong></li> <li><strong>用xaml定义控件样式</strong></li></ol> <p><strong>一.明确控件需求</strong></p> <p>控件功能如下:</p> <ol> <li>可以垂直,水平排列</li> <li>可以分行,列</li> <li>为子项设置Margin</li></ol> <p>二.<strong>定义依赖属性</strong></p> <p>为避免重复定义属性，为两个控件定义公共类ListControl,从ListBox继承</p> <p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf54_D5A8/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf54_D5A8/image_thumb_2.png" width="410" height="247"></a> </p> <p>然后定义依赖属性</p><pre class="code"><span style="color: blue">namespace </span>WPF.Controls
{
    <span style="color: gray">/// &lt;summary&gt;
    /// </span><span style="color: green">this is a base class for CheckBoxList and RadioButtonList
    </span><span style="color: gray">/// </span><span style="color: green">this class define some common property
    </span><span style="color: gray">/// &lt;/summary&gt;
    </span><span style="color: blue">public abstract class </span><span style="color: #2b91af">ListControl </span>: <span style="color: #2b91af">ListBox
    </span>{

        <span style="color: blue">#region </span>Orientation

        <span style="color: gray">/// &lt;summary&gt;
        /// </span><span style="color: green">Gets or sets a value that indicates the dimension by which child elements are stacked.
        </span><span style="color: gray">/// </span><span style="color: green">This is a dependency property.
        </span><span style="color: gray">/// &lt;/summary&gt;
        </span><span style="color: blue">public </span><span style="color: #2b91af">Orientation </span>Orientation
        {
            <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: #2b91af">Orientation</span>)GetValue(OrientationProperty); }
            <span style="color: blue">set </span>{ SetValue(OrientationProperty, <span style="color: blue">value</span>); }
        }


        <span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>OrientationProperty =
            <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Orientation"</span>, <span style="color: blue">typeof</span>(<span style="color: #2b91af">Orientation</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">ListControl</span>),
            <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(<span style="color: #2b91af">Orientation</span>.Vertical, <span style="color: blue">new </span><span style="color: #2b91af">PropertyChangedCallback</span>(OrientationChangedCallback)));

        <span style="color: blue">public static void </span>OrientationChangedCallback(<span style="color: #2b91af">DependencyObject </span>d, <span style="color: #2b91af">DependencyPropertyChangedEventArgs </span>e)
        {
            <span style="color: #2b91af">ListControl </span>control = d <span style="color: blue">as </span><span style="color: #2b91af">ListControl</span>;
            <span style="color: blue">if </span>(control.Orientation == <span style="color: #2b91af">Orientation</span>.Horizontal)
            {
                control.Columns = 0;
                control.Rows = 1;
            }
            <span style="color: blue">else if </span>(control.Orientation == <span style="color: #2b91af">Orientation</span>.Vertical)
            {
                control.Rows = 0;
                control.Columns = 1;
            }
        }

        <span style="color: blue">#endregion

        #region </span>Columns

        <span style="color: gray">/// &lt;summary&gt;
        /// </span><span style="color: green">Get or set a value that indicates which Columns list item should appear in.
        </span><span style="color: gray">/// </span><span style="color: green">This is a dependency property.
        </span><span style="color: gray">/// &lt;/summary&gt;
        </span><span style="color: blue">public int </span>Columns
        {
            <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">int</span>)GetValue(ColumnsProperty); }
            <span style="color: blue">set </span>{ SetValue(ColumnsProperty, <span style="color: blue">value</span>); }
        }

        <span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>ColumnsProperty =
            <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Columns"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">int</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">ListControl</span>), <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(1));

        <span style="color: blue">#endregion

        #region </span>Rows

        <span style="color: gray">/// &lt;summary&gt;
        /// </span><span style="color: green">Get or set a value that indicates which Rows list item should appear in.
        </span><span style="color: gray">/// </span><span style="color: green">This is a dependency property.
        </span><span style="color: gray">/// &lt;/summary&gt;
        </span><span style="color: blue">public int </span>Rows
        {
            <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">int</span>)GetValue(RowsProperty); }
            <span style="color: blue">set </span>{ SetValue(RowsProperty, <span style="color: blue">value</span>); }
        }

        <span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>RowsProperty =
            <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Rows"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">int</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">ListControl</span>), <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(0));

        <span style="color: blue">#endregion

        public </span><span style="color: #2b91af">Thickness </span>SubMargin
        {
            <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: #2b91af">Thickness</span>)GetValue(SubMarginProperty); }
            <span style="color: blue">set </span>{ SetValue(SubMarginProperty, <span style="color: blue">value</span>); }
        }

        <span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>SubMarginProperty =
            <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"SubMargin"</span>, <span style="color: blue">typeof</span>(<span style="color: #2b91af">Thickness</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">ListControl</span>), 
            <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(<span style="color: blue">new </span><span style="color: #2b91af">Thickness</span>(2,2,2,0)));

    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<p></p>
<p></p>
<p>以上依赖属性定义的非常简单,之所以定义成依赖属性是因为可以进行属性绑定操作.</p>
<p>三.<strong>重写默认样式属性元数据</strong></p><pre class="code"><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Represents a control that a user can choose one from list options in a group radiobutton
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">public class </span><span style="color: #2b91af">RadioButtonList </span>: <span style="color: #2b91af">ListControl
</span>{
    <span style="color: blue">static </span>RadioButtonList()
    {
        DefaultStyleKeyProperty.OverrideMetadata(<span style="color: blue">typeof</span>(<span style="color: #2b91af">RadioButtonList</span>)
            , <span style="color: blue">new </span><span style="color: #2b91af">FrameworkPropertyMetadata</span>(<span style="color: blue">typeof</span>(<span style="color: #2b91af">RadioButtonList</span>)));
    }
}

<span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Contains a list of selectable CheckBox items 
</span><span style="color: gray">/// </span><span style="color: green">Represents a control that a user can choose from a list options in a group of CheckBox
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">public class </span><span style="color: #2b91af">CheckBoxList </span>: <span style="color: #2b91af">ListControl
</span>{
    <span style="color: blue">static </span>CheckBoxList()
    {
        DefaultStyleKeyProperty.OverrideMetadata(<span style="color: blue">typeof</span>(<span style="color: #2b91af">CheckBoxList</span>)
            , <span style="color: blue">new </span><span style="color: #2b91af">FrameworkPropertyMetadata</span>(<span style="color: blue">typeof</span>(<span style="color: #2b91af">CheckBoxList</span>)));
    }
}</pre>
<p><strong>四.用xaml定义控件样式</strong></p>
<p>默认项目中会有一个Generic.xaml文件,我们要把样式定义在此文件中</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf54_D5A8/image_8.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf54_D5A8/image_thumb_3.png" width="206" height="244"></a> </p>
<p>控件样式定义</p>
<p>(1)<span style="color: red">ListControl</span></p><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">Style </span><span style="color: red">TargetType</span><span style="color: blue">="{</span><span style="color: #a31515">x</span><span style="color: blue">:</span><span style="color: #a31515">Type </span><span style="color: red">local</span><span style="color: blue">:</span><span style="color: red">ListControl</span><span style="color: blue">}" </span><span style="color: red">BasedOn</span><span style="color: blue">="{</span><span style="color: #a31515">StaticResource </span><span style="color: blue">{</span><span style="color: #a31515">x</span><span style="color: blue">:</span><span style="color: #a31515">Type </span><span style="color: red">ListBox</span><span style="color: blue">}}"&gt;
    &lt;</span><span style="color: #a31515">Setter </span><span style="color: red">Property</span><span style="color: blue">="ItemsPanel"&gt;
        &lt;</span><span style="color: #a31515">Setter.Value</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">ItemsPanelTemplate</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">UniformGrid </span><span style="color: red">HorizontalAlignment</span><span style="color: blue">="Left" </span><span style="color: red">VerticalAlignment</span><span style="color: blue">="Top"
                    </span><span style="color: red">Rows</span><span style="color: blue">="{</span><span style="color: #a31515">Binding </span><span style="color: red">Path</span><span style="color: blue">=Rows,</span><span style="color: red">RelativeSource</span><span style="color: blue">={</span><span style="color: #a31515">RelativeSource </span><span style="color: red">FindAncestor</span><span style="color: blue">,</span><span style="color: red">AncestorType</span><span style="color: blue">={</span><span style="color: #a31515">x</span><span style="color: blue">:</span><span style="color: #a31515">Type </span><span style="color: red">local</span><span style="color: blue">:</span><span style="color: red">ListControl</span><span style="color: blue">}}}" 
                    </span><span style="color: red">Columns</span><span style="color: blue">="{</span><span style="color: #a31515">Binding </span><span style="color: red">Path</span><span style="color: blue">=Columns,</span><span style="color: red">RelativeSource</span><span style="color: blue">={</span><span style="color: #a31515">RelativeSource </span><span style="color: red">FindAncestor</span><span style="color: blue">,</span><span style="color: red">AncestorType</span><span style="color: blue">={</span><span style="color: #a31515">x</span><span style="color: blue">:</span><span style="color: #a31515">Type </span><span style="color: red">local</span><span style="color: blue">:</span><span style="color: red">ListControl</span><span style="color: blue">}}}"&gt;&lt;/</span><span style="color: #a31515">UniformGrid</span><span style="color: blue">&gt;
            &lt;/</span><span style="color: #a31515">ItemsPanelTemplate</span><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">Setter.Value</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">Setter</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Setter </span><span style="color: red">Property</span><span style="color: blue">="BorderThickness" </span><span style="color: red">Value</span><span style="color: blue">="0" /&gt;
    &lt;</span><span style="color: #a31515">Setter </span><span style="color: red">Property</span><span style="color: blue">="Background" </span><span style="color: red">Value</span><span style="color: blue">="Transparent" /&gt;
&lt;/</span><span style="color: #a31515">Style</span><span style="color: blue">&gt;</span></pre>(2)<span style="color: red">RadioButtonList</span><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">Style </span><span style="color: red">TargetType</span><span style="color: blue">="{</span><span style="color: #a31515">x</span><span style="color: blue">:</span><span style="color: #a31515">Type </span><span style="color: red">local</span><span style="color: blue">:</span><span style="color: red">RadioButtonList</span><span style="color: blue">}" </span><span style="color: red">BasedOn</span><span style="color: blue">="{</span><span style="color: #a31515">StaticResource </span><span style="color: blue">{</span><span style="color: #a31515">x</span><span style="color: blue">:</span><span style="color: #a31515">Type </span><span style="color: red">local</span><span style="color: blue">:</span><span style="color: red">ListControl</span><span style="color: blue">}}"&gt;
    &lt;</span><span style="color: #a31515">Style.Resources</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">Style </span><span style="color: red">TargetType</span><span style="color: blue">="ListBoxItem"&gt;
            &lt;</span><span style="color: #a31515">Setter </span><span style="color: red">Property</span><span style="color: blue">="Margin" </span><span style="color: red">Value</span><span style="color: blue">="2, 2, 2, 0" /&gt;
            &lt;</span><span style="color: #a31515">Setter </span><span style="color: red">Property</span><span style="color: blue">="Template"&gt;
                &lt;</span><span style="color: #a31515">Setter.Value</span><span style="color: blue">&gt;
                    &lt;</span><span style="color: #a31515">ControlTemplate </span><span style="color: red">TargetType</span><span style="color: blue">="ListBoxItem"&gt;
                            &lt;</span><span style="color: #a31515">RadioButton 
                                </span><span style="color: red">Margin</span><span style="color: blue">="{</span><span style="color: #a31515">Binding </span><span style="color: red">Path</span><span style="color: blue">=SubMargin,</span><span style="color: red">RelativeSource</span><span style="color: blue">={</span><span style="color: #a31515">RelativeSource </span><span style="color: red">FindAncestor</span><span style="color: blue">,</span><span style="color: red">AncestorType</span><span style="color: blue">={</span><span style="color: #a31515">x</span><span style="color: blue">:</span><span style="color: #a31515">Type </span><span style="color: red">local</span><span style="color: blue">:</span><span style="color: red">RadioButtonList</span><span style="color: blue">}}}"
                                </span><span style="color: red">IsChecked</span><span style="color: blue">="{</span><span style="color: #a31515">Binding </span><span style="color: red">IsSelected</span><span style="color: blue">, </span><span style="color: red">RelativeSource</span><span style="color: blue">={</span><span style="color: #a31515">RelativeSource </span><span style="color: red">TemplatedParent</span><span style="color: blue">},</span><span style="color: red">Mode</span><span style="color: blue">=TwoWay}"&gt;
                                &lt;</span><span style="color: #a31515">RadioButton.Content</span><span style="color: blue">&gt;
                                    &lt;</span><span style="color: #a31515">ContentPresenter</span><span style="color: blue">/&gt;
                                &lt;/</span><span style="color: #a31515">RadioButton.Content</span><span style="color: blue">&gt;
                            &lt;/</span><span style="color: #a31515">RadioButton</span><span style="color: blue">&gt;
                    &lt;/</span><span style="color: #a31515">ControlTemplate</span><span style="color: blue">&gt;
                &lt;/</span><span style="color: #a31515">Setter.Value</span><span style="color: blue">&gt;
            &lt;/</span><span style="color: #a31515">Setter</span><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">Style</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">Style.Resources</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">Style</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>(3)<span style="color: red">CheckBoxList</span><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">Style </span><span style="color: red">TargetType</span><span style="color: blue">="{</span><span style="color: #a31515">x</span><span style="color: blue">:</span><span style="color: #a31515">Type </span><span style="color: red">local</span><span style="color: blue">:</span><span style="color: red">CheckBoxList</span><span style="color: blue">}" </span><span style="color: red">BasedOn</span><span style="color: blue">="{</span><span style="color: #a31515">StaticResource </span><span style="color: blue">{</span><span style="color: #a31515">x</span><span style="color: blue">:</span><span style="color: #a31515">Type </span><span style="color: red">local</span><span style="color: blue">:</span><span style="color: red">ListControl</span><span style="color: blue">}}"&gt;
    &lt;</span><span style="color: #a31515">Setter </span><span style="color: red">Property</span><span style="color: blue">="SelectionMode" </span><span style="color: red">Value</span><span style="color: blue">="Multiple"&gt;&lt;/</span><span style="color: #a31515">Setter</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Style.Resources</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">Style </span><span style="color: red">TargetType</span><span style="color: blue">="ListBoxItem"&gt;
            &lt;</span><span style="color: #a31515">Setter </span><span style="color: red">Property</span><span style="color: blue">="Margin" </span><span style="color: red">Value</span><span style="color: blue">="2, 2, 2, 0" /&gt;
            &lt;</span><span style="color: #a31515">Setter </span><span style="color: red">Property</span><span style="color: blue">="Template"&gt;
                &lt;</span><span style="color: #a31515">Setter.Value</span><span style="color: blue">&gt;
                    &lt;</span><span style="color: #a31515">ControlTemplate </span><span style="color: red">TargetType</span><span style="color: blue">="ListBoxItem"&gt;
                            &lt;</span><span style="color: #a31515">CheckBox
                                </span><span style="color: red">Margin</span><span style="color: blue">="{</span><span style="color: #a31515">Binding </span><span style="color: red">Path</span><span style="color: blue">=SubMargin,</span><span style="color: red">RelativeSource</span><span style="color: blue">={</span><span style="color: #a31515">RelativeSource </span><span style="color: red">FindAncestor</span><span style="color: blue">,</span><span style="color: red">AncestorType</span><span style="color: blue">={</span><span style="color: #a31515">x</span><span style="color: blue">:</span><span style="color: #a31515">Type </span><span style="color: red">local</span><span style="color: blue">:</span><span style="color: red">RadioButtonList</span><span style="color: blue">}}}"
                                </span><span style="color: red">IsChecked</span><span style="color: blue">="{</span><span style="color: #a31515">Binding </span><span style="color: red">IsSelected</span><span style="color: blue">, </span><span style="color: red">RelativeSource</span><span style="color: blue">={</span><span style="color: #a31515">RelativeSource </span><span style="color: red">TemplatedParent</span><span style="color: blue">},</span><span style="color: red">Mode</span><span style="color: blue">=TwoWay}"&gt;
                                &lt;</span><span style="color: #a31515">CheckBox.Content</span><span style="color: blue">&gt;
                                    &lt;</span><span style="color: #a31515">ContentPresenter</span><span style="color: blue">/&gt;
                                &lt;/</span><span style="color: #a31515">CheckBox.Content</span><span style="color: blue">&gt;
                            &lt;/</span><span style="color: #a31515">CheckBox</span><span style="color: blue">&gt;
                    &lt;/</span><span style="color: #a31515">ControlTemplate</span><span style="color: blue">&gt;
                &lt;/</span><span style="color: #a31515">Setter.Value</span><span style="color: blue">&gt;
            &lt;/</span><span style="color: #a31515">Setter</span><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">Style</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">Style.Resources</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">Style</span><span style="color: blue">&gt;</span></pre>
<p>OK,到这里就完事了.我们发现我们并不需要写多少代码,就可以实现一个控件.而且RadioButtonList和CheckBoxList几乎没有代码,仅仅只是重写了样式而已,这也是WPF定义控件的基本概念,一些变的都是如此简单.</p>
<p><a href="http://cid-e61fe49e5e4bce66.skydrive.live.com/self.aspx/.Public/WPFCustomControlTutorial02/WPFControlTutorialPart5.rar">Demo下载</a></p><img src="http://www.cnblogs.com/Clingingboy/aggbug/1662562.html?type=1" width="1" height="1" alt=""/><p>评论: 4　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/03/1662562.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/03/1662562.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56819/" target="_blank">Yahoo脑震荡 关闭服务汇总贴</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56824/" target="_blank">2003年微软遭遇iTunes：我们彻底晕头转向了</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56823/" target="_blank">百度数据能被“作弊”软件篡改？百度:追究侵权</a><span style="color:gray">(2010-02-10 11:52)</span><br/>· <a href="http://news.cnblogs.com/n/56822/" target="_blank">Ksplice为Linux提供永远不用重启服务</a><span style="color:gray">(2010-02-10 11:51)</span><br/>· <a href="http://news.cnblogs.com/n/56821/" target="_blank">视频网站2010年格局之变：七成企业将被淘汰</a><span style="color:gray">(2010-02-10 11:48)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>wpf控件开发基础(4) -属性系统(3)</title><link>http://www.cnblogs.com/Clingingboy/archive/2010/02/02/1661842.html</link><dc:creator>Clingingboy</dc:creator><author>Clingingboy</author><pubDate>Tue, 02 Feb 2010 07:08:00 GMT</pubDate><guid>http://www.cnblogs.com/Clingingboy/archive/2010/02/02/1661842.html</guid><description><![CDATA[<p>阅读: 902 评论: 5 作者: <a href="http://www.cnblogs.com/Clingingboy/" target="_blank">Clingingboy</a> 发表于 2010-02-02 15:08 <a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/02/1661842.html" target="_blank">原文链接</a></p><h2>知识回顾</h2> <p><a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661370.html">接上篇</a>,上篇我们真正接触到了依赖属性的用法,以及依赖属性的属性元数据的用法,并且也实实在在地解决了之前<a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661090.html">第二篇</a>提到的一系列问题.来回顾一下</p> <ol> <li><strong>属性默认值</strong></li> <li><strong>属性变更通知</strong></li> <li><strong>属性强制回调</strong></li></ol> <p>本篇将继续讨论上一篇提到的问题,主题依然是属性元数据.</p> <h2>内容概要</h2> <ol> <li>属性值验证</li> <li>默认值问题</li> <li>依赖属性的不变与可变</li> <li>属性元数据的唯一性</li> <li>重写属性元数据</li> <li>改写属性元数据</li></ol> <h2>一.属性值验证</h2> <p>依赖属性具备属性验证的功能,其也会对依赖属性默认值进行验证,在DependencyProperty的Register方法中最后一个参数为<strong>ValidateValueCallback</strong>,用于属性值验证,如下代码</p><pre class="code"><span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>AgeProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Age"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">int</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCustomPeople</span>),
    <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(1), <span style="color: blue">new </span><span style="color: #2b91af">ValidateValueCallback</span>(AgeValidateValueCallback));

<span style="color: blue">public virtual int </span>Age
{
    <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">int</span>)GetValue(AgeProperty); }
    <span style="color: blue">set </span>{ SetValue(AgeProperty, <span style="color: blue">value</span>); }
}

<span style="color: blue">public static bool </span>AgeValidateValueCallback(<span style="color: blue">object </span>value)
{
    <span style="color: blue">int </span>age=(<span style="color: blue">int</span>)value;
    <span style="color: blue">if </span>(age &lt; 1) <span style="color: blue">return false</span>;
    <span style="color: blue">return true</span>;
}</pre>
<p><span style="color: #2b91af">ValidateValueCallback</span>有一个传入的参数(即依赖属性值)和一个返回值(表示属性值是否是正确的).</p>
<p><strong>注意:<br>1.当返回值为false的时候,将会抛出异常<br>2.不要试图在该回调方法中校正传入的值类型(即使引用类型也不符合逻辑),其主要职责在于验证.</strong></p>
<p>此功能用的不是很频繁,因为返回false会抛异常,还要额外处理.再说强制回调方法也可以处理.</p>
<h2>二.默认值问题</h2>
<p>上一篇有讲到依赖属性的默认值问题</p>
<p>在构造函数里给属性赋值并不能解决问题(这是依赖属性默认值带来的额外问题,因为其是静态属性)</p>
<p><strong>类继承</strong>带来的默认值重写问题,看以下代</p><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">RootClass
</span>{
    <span style="color: blue">public </span>RootClass()
    {
        <span style="color: blue">this</span>.Name = <span style="color: #a31515">"RootClass"</span>;
    }
    <span style="color: blue">public string </span>Name { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
}

<span style="color: blue">public class </span><span style="color: #2b91af">SubClass </span>: <span style="color: #2b91af">RootClass
</span>{
    <span style="color: blue">public </span>SubClass()
    {
        <span style="color: blue">this</span>.Name = <span style="color: #a31515">"SubClass"</span>;
    }
}</pre>
<p>上面代码应该没问题,但如果这样就有问题了</p><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">RootClass
</span>{
    <span style="color: blue">public </span>RootClass()
    {
        Name = <span style="color: #a31515">"RootClass"</span>;
    }
    <span style="color: blue">public static string </span>Name { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
}

<span style="color: blue">public class </span><span style="color: #2b91af">SubClass </span>: <span style="color: #2b91af">RootClass
</span>{
    <span style="color: blue">public </span>SubClass()
    {
        Name = <span style="color: #a31515">"SubClass"</span>;
    }
}</pre>
<p>如果是静态属性的话,子类一旦改写就会改变父类,破坏内部逻辑</p>
<p>那么就需要<strong>保证属性在每个类默认值的唯一性.</strong></p>
<h2>三.依赖属性的不变与可变</h2>
<p>上篇有提到过这样一句话</p>
<p><strong>(依赖属性)属性名字,属性类型,属性所有者类型一经注册将无法更改</strong></p>
<p>这便不可变的地方,即使在子类重写也不行.<br>但依赖属性的默认值是可以修改的,修改的前提是保证父类的属性默认值不被影响,上篇我们有提出疑问,给默认值为什么需要<strong>属性元数据</strong>(PropertyMetadata),以下的代码也应该走的通</p><pre class="code">    <span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>NameProperty =
<span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Name"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">string</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCustomPeople</span>),
<span style="color: blue">string</span>.Empty);</pre><a href="http://11011.net/software/vspaste"></a>
<p>是的,若依赖属性内部有一个列表维护默认值,也保证了在不同类型中默认值不会发生错误.这样的代码是没问题的,但不要忘了,还有属性变更通知和属性强制回调.<strong>PropertyMetadata把依赖属性可变的行为全部抽取出来了</strong>,我想这样做的原因可以保持依赖属性功能的清晰程度(个人猜想,但确实有这样的效果).那么就意味着我们可以重写属性元数据.</p>
<h2>四.属性元数据的唯一性</h2>
<p>DependencyProperty提供了OverrideMetadata方法重写属性元数据,但一个依赖属性在同一个类中不允许重写,即在同一类型中,保证属性元数据在依赖属性中的唯一性,如下代码是错误的</p><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">DPCategory </span>: <span style="color: #2b91af">DependencyObject
</span>{
    <span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>NameProperty =
           <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Name"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">string</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCategory</span>),
           <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(<span style="color: blue">string</span>.Empty));

    <span style="color: blue">public void </span>TestOverrideMetadata()
    {
        <span style="color: green">//wrong
        </span>NameProperty.OverrideMetadata(<span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCategory</span>), <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(<span style="color: #a31515">"WPF"</span>));
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>将会抛出异常</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf43_14022/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf43_14022/image_thumb.png" width="667" height="84"></a> </p>
<h2>五.重写属性元数据</h2>
<p>继承的子类允许重写属性元数据,如下代码</p><a href="http://11011.net/software/vspaste"></a><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">DPWPFCategory </span>: <span style="color: #2b91af">DPCategory
</span>{
    <span style="color: blue">public void </span>TestOverrideMetadata()
    {
        NameProperty.OverrideMetadata(<span style="color: blue">typeof</span>(<span style="color: #2b91af">DPWPFCategory</span>), <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(<span style="color: #a31515">"WPF"</span>));
        <span style="color: #2b91af">Console</span>.WriteLine(NameProperty.GetMetadata(<span style="color: blue">typeof</span>(<span style="color: #2b91af">DPWPFCategory</span>)).DefaultValue);
        <span style="color: green">//output 30
    </span>}
}</pre><a href="http://11011.net/software/vspaste"></a>
<p><strong>注意:</strong>在重写属性元数据时,应该要知道一下规则.<br><strong>1.重写元数据是一个以重写元数据为主的合并的过程,即子类的重写后的元数据会与父类的进行合并</strong></p>
<p>我们在父类定义一个Group的依赖属性</p><pre class="code"><span style="color: blue">public string </span>Group
{
    <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">string</span>)GetValue(GroupProperty); }
    <span style="color: blue">set </span>{ SetValue(GroupProperty, <span style="color: blue">value</span>); }
}
<span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>GroupProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Group"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">string</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCategory</span>), 
    <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(<span style="color: blue">string</span>.Empty,<span style="color: blue">new </span><span style="color: #2b91af">PropertyChangedCallback</span>(GroupPropertyChangedCallback)));

<span style="color: blue">public static void </span>GroupPropertyChangedCallback(<span style="color: #2b91af">DependencyObject </span>d, <span style="color: #2b91af">DependencyPropertyChangedEventArgs </span>e)
{
    <span style="color: #2b91af">Console</span>.WriteLine(e.NewValue);
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>然后在子类重写此依赖属性的元数据</p><pre class="code"><span style="color: blue">public void </span>TestOverrideMergeMetadata()
{
    GroupProperty.OverrideMetadata(<span style="color: blue">typeof</span>(<span style="color: #2b91af">DPWPFCategory</span>), <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(<span style="color: #a31515">"Computer Technology"</span>));
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: blue">this</span>.Group);
    <span style="color: blue">this</span>.Group = <span style="color: #a31515">"Technology"</span>;
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>输出结果,当属性值发生变化时,父类的属性变更通知回调方法就会触发</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf43_14022/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf43_14022/image_thumb_1.png" width="259" height="84"></a> </p>
<p><strong>2.实例匹配(Type.IsAssignableFrom 返回为true)</strong></p>
<p><strong>注意:</strong>要重写的父类属性元数据<strong>类型</strong>必须要是重写的属性元数据的<strong>父类或者与之类型相同.</strong>如下为属性元数据的继承关系</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf43_14022/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf43_14022/image_thumb_2.png" width="248" height="356"></a> </p>
<p>可以看出如果用FrameworkPropertyMetadata来重写的话是最保险的</p>
<p><strong>如下示例</strong></p><pre class="code"><span style="color: blue">public int </span>Order
{
    <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">int</span>)GetValue(OrderProperty); }
    <span style="color: blue">set </span>{ SetValue(OrderProperty, <span style="color: blue">value</span>); }
}

<span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>OrderProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Order"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">int</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCategory</span>), <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(0));
<span style="color: green">//UIPropertyMetadata</span></pre><a href="http://11011.net/software/vspaste"></a>
<p>注意父类的属性元数据为<span style="color: #2b91af">UIPropertyMetadata<font color="#000000">,以下子类重写的属性元数据类型为<span style="color: #2b91af">PropertyMetadata<font color="#000000"> 即会报错.</font></span></font></span></p><pre class="code"><span style="color: blue">public void </span>TestOverrideDriveMetadata()
{
    OrderProperty.OverrideMetadata(<span style="color: blue">typeof</span>(<span style="color: #2b91af">DPWPFCategory</span>), <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(1));
    <span style="color: green">//wrong
    //must &gt;=UIPropertyMetadata
</span>}</pre><a href="http://11011.net/software/vspaste"></a>
<p><span style="color: #2b91af"></span><font color="#2b91af"></font>输出</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf43_14022/image_8.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf43_14022/image_thumb_3.png" width="677" height="85"></a> </p>
<h2>六.改写属性元数据</h2>
<p>改写与重写有几点不同.</p>
<ol>
<li>改写是将已存在的依赖属性添加到不同类型当中</li>
<li>改写不是一个合并属性元数据的过程,改写后的是全新的</li></ol>
<p>如下:<br>为一个全新的类型添加已有依赖属性,并重写属性元数据,重写后将不会触发<span style="color: #2b91af"><font color="#000000">DPCategory类型的GroupProperty属性变更通知,不会影响原依赖属性逻辑</font></span></p><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">DPGroup</span>:<span style="color: #2b91af">DependencyObject
</span>{
    <span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>GroupProperty =
    <span style="color: #2b91af">DPCategory</span>.GroupProperty.AddOwner(<span style="color: blue">typeof</span>(<span style="color: #2b91af">DPGroup</span>),
    <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(<span style="color: #a31515">"Technology"</span>));
    <span style="color: blue">public string </span>Group
    {
        <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">string</span>)GetValue(GroupProperty); }
        <span style="color: blue">set </span>{ SetValue(GroupProperty, <span style="color: blue">value</span>); }
    }

    <span style="color: blue">public void </span>TestAddOwnerMetadata()
    {
        <span style="color: #2b91af">Console</span>.WriteLine(Group);
        <span style="color: blue">this</span>.Group = <span style="color: #a31515">"Computer Technology"</span>;
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<p><strong>注意:如果在子类进行此操作，将与重写效果一样</strong></p>
<p></p>
<p></p>
<p></p>
<p>本篇主要讲到了属性元数据的一些特点及注意点.FrameworkPropertyMetadata还有许多特性,但必须有实际场景结合.所以这里无法展开.讲了这么多貌似都没触及到WPF什么事,这部分也是比较枯燥,但却非常重要.下篇继续,然后依赖属性就告一段落.</p>
<p><a href="http://cid-e61fe49e5e4bce66.skydrive.live.com/self.aspx/.Public/WPFCustomControlTutorial02/WPFControlTutorialPart4.rar">Demo下载</a></p><img src="http://www.cnblogs.com/Clingingboy/aggbug/1661842.html?type=1" width="1" height="1" alt=""/><p>评论: 5　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/02/1661842.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/02/1661842.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56819/" target="_blank">Yahoo脑震荡 关闭服务汇总贴</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56824/" target="_blank">2003年微软遭遇iTunes：我们彻底晕头转向了</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56823/" target="_blank">百度数据能被“作弊”软件篡改？百度:追究侵权</a><span style="color:gray">(2010-02-10 11:52)</span><br/>· <a href="http://news.cnblogs.com/n/56822/" target="_blank">Ksplice为Linux提供永远不用重启服务</a><span style="color:gray">(2010-02-10 11:51)</span><br/>· <a href="http://news.cnblogs.com/n/56821/" target="_blank">视频网站2010年格局之变：七成企业将被淘汰</a><span style="color:gray">(2010-02-10 11:48)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>wpf控件开发基础(3) -属性系统(2)</title><link>http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661370.html</link><dc:creator>Clingingboy</dc:creator><author>Clingingboy</author><pubDate>Mon, 01 Feb 2010 14:20:00 GMT</pubDate><guid>http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661370.html</guid><description><![CDATA[<p>阅读: 919 评论: 0 作者: <a href="http://www.cnblogs.com/Clingingboy/" target="_blank">Clingingboy</a> 发表于 2010-02-01 22:20 <a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661370.html" target="_blank">原文链接</a></p><p>&nbsp;&nbsp;&nbsp; 上篇说明了属性存在的一系列问题.</p> <ol> <li><strong>属性默认值</strong>,可以保证属性的有效性.  <li><strong>属性验证有效性</strong>,可以对输入的属性进行校验  <li><strong>属性强制回调,</strong> 即不管属性有无发生变化,都要做出通知.  <li><strong>属性变更通知</strong>,当属性发生变化可以通知程序作出一系列的处理.</li></ol> <p>这里还没WPF什么事,我们来看看依赖属性是如何解决以上问题的.</p> <h4>内容概要</h4> <ul> <li>定义第一个最简单的依赖属性  <li>依赖属性值基本操作  <li>属性包装器  <li>属性元数据(PropertyMetadata)  <li>属性元数据基本行为</li></ul> <p><strong>MSDN的原话虽然生硬,但准确定性毋庸置疑.当理解后再来看别有一番体会.</strong></p> <h2>一.定义第一个最简单的依赖属性<br></h2> <p><strong>MSDN原话:</strong>Windows Presentation Foundation (WPF) 提供了一组服务，这些服务可用于扩展公共语言运行时 (CLR) 属性的功能。这些服务通常统称为 WPF 属性系统。由 WPF 属性系统支持的属性称为依赖项属性。<br>我们来定义一个Age依赖属性,如下代码</p><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">DPCustomPeople</span><span style="color: #2b91af">
</span>{
    <span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>AgeProperty =
        <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Age"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">int</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCustomPeople</span>));

    <span style="color: blue">public void </span>DisplayAgeProperty()
    {
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"DPName:" </span>+ <span style="color: #2b91af">DPCustomPeople</span>.AgeProperty.Name);
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"DPPropertyType:" </span>+ <span style="color: #2b91af">DPCustomPeople</span>.AgeProperty.PropertyType);
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"DPOwnerType:" </span>+ <span style="color: #2b91af">DPCustomPeople</span>.AgeProperty.OwnerType);
    }
}</pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<p>然后调用输出结果</p><pre class="code"><span style="color: blue">class </span><span style="color: #2b91af">Program
</span>{
    <span style="color: blue">static void </span>Main(<span style="color: blue">string</span>[] args)
    {
        <span style="color: #2b91af">DPCustomPeople </span>people = <span style="color: blue">new </span><span style="color: #2b91af">DPCustomPeople</span>();
        people.DisplayAgeProperty();
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>你可能对<strong>DependencyProperty</strong>类比较陌生,DependencyProperty类提供了依赖属性的一些基本特征</p>
<p>注册依赖属性的方法是调用DependencyProperty的静态<strong>Register</strong>方法,其提供了多个重载方法,但以下三个步骤是必须的.注册完毕是其是一个<strong>静态属性</strong></p>
<ol>
<li>提供注册的名字(Name)<span style="color: #a31515">"Age"</span> 
<li>注册属性类型(PropertyType)<span style="color: blue">typeof</span>(<span style="color: blue">int</span>) 
<li>注册该依赖属性的所有者类型(OwnerType)<span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCustomPeople</span>)</li></ol>
<p><strong>注意:属性名字,属性类型,属性所有者类型一经注册将无法更改</strong></p>
<p>以下为输出结果</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_thumb.png" width="590" height="119"></a>&nbsp;</p>
<h2>二.依赖属性值基本操作(取值与赋值)<br></h2>
<p>定义了Age依赖属性以后,那么我们理应可以对属性进行取值,赋值操作.DependencyProperty本身并不提供这些操作,而是由DependencyObject来负责</p>
<p><strong>DependencyObject</strong> 表示一个参与依赖项属性系统的对象.</p>
<p>所以要求定义的类要<strong>继承自</strong>DependencyObject,那么改写<span style="color: #2b91af">DPCustomPeople</span></p><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">DPCustomPeople</span>:System.Windows.<span style="color: #2b91af">DependencyObject
</span>{
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>基本的取值赋值操作<strong>GetValue和SetValue方法</strong></p><pre class="code"><span style="color: blue">public void </span>DPPropertyBasicOperator()
{
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Age:" </span>+ <span style="color: blue">this</span>.GetValue(<span style="color: #2b91af">DPCustomPeople</span>.AgeProperty));
    <span style="color: blue">this</span>.SetValue(<span style="color: #2b91af">DPCustomPeople</span>.AgeProperty, 24);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"ChangedAge:" </span>+ <span style="color: blue">this</span>.GetValue(<span style="color: #2b91af">DPCustomPeople</span>.AgeProperty));
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>输出结果</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_thumb_1.png" width="244" height="88"></a> </p>
<h2>三.属性包装器</h2>
<p>用GetValue和SetValue方法对值操作不大美观,所以我们可以对其包装一下,定义Age属性</p><pre class="code"><span style="color: blue">public int </span>Age
{
    <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">int</span>)GetValue(AgeProperty); }
    <span style="color: blue">set </span>{ SetValue(AgeProperty, <span style="color: blue">value</span>); }
}</pre><a href="http://11011.net/software/vspaste"></a>
<p><strong>注意:依赖属性包装命名规是把后面的Property去掉</strong></p><pre class="code"><span style="color: blue">public void </span>DPPropertyBasicOperatorUsingProperty()
{
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Age:" </span>+ <span style="color: blue">this</span>.Age);
    <span style="color: blue">this</span>.Age=24;
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"ChangedAge:" </span>+ <span style="color: blue">this</span>.Age);
}</pre>
<p></p>
<p>以上的代码看起来是不是更加的简洁呢</p>
<h2>四.属性元数据(PropertyMetadata)</h2>
<p><strong>MSDN原话:</strong>Windows Presentation Foundation (WPF) 属性系统包括一个元数据报告系统，该系统不局限于可以通过反射或常规公共语言运行时 (CLR) 特征报告的关于某个属性的内容。</p>
<p>说到属性元数据,第一个让人想到的就是.net的<strong>Attribute</strong></p><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">Person
</span>{
    [<span style="color: #2b91af">DefaultValue</span>(200),<span style="color: #2b91af">Category</span>(<span style="color: #a31515">"Layout"</span>)]
    <span style="color: blue">public int </span>Width { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
}</pre>
<p><strong>Attribute</strong>需要借助Visual Studio的力量,使得IDE对<strong>Attribute</strong>进行很友好的支持,或者依靠反射来赋值.</p>
<p>但离开这些技术的,通过正常途径,new出一个新的实例,加了<strong>Attribute</strong>的属性毫无效果.我们不能依赖这些<strong>Attribute</strong>来保证属性的一些基本特性(如默认值).依赖属性的属性元数据与上述描述的元数据不同.</p>
<p>依赖项属性的元数据</p>
<ol>
<li>可以由定义依赖项属性的类来<strong>唯一地指定</strong> 
<li>可以在依赖项属性<strong>添加到另一个类时进行更改</strong> 
<li>可以由所有从定义基类继承依赖项属性的<strong>派生类来明确地重写</strong></li></ol>
<p><strong>以上语言很生硬，但却说明了意图.但我们总无法第一时间领会设计者的想法.暂且先知道有这个概念的存在</strong></p>
<h2>五.属性元数据基本行为</h2>
<p>属性元数据基本行为为依赖属性提供了3个功能,这也是本文刚提出来的问题.</p>
<ol>
<li>默认属性 
<li>属性通知 
<li>属性强制回调</li></ol>
<p>先来看一看一个完整PropertyMetadata的构造函数,如果没有为依赖属性设置默认的PropertyMetadata的话,内部会为依赖属性自动创建一个PropertyMetadata对象.</p><pre class="code"><span style="color: blue">public </span>PropertyMetadata(<span style="color: blue">object </span>defaultValue, <span style="color: #2b91af">PropertyChangedCallback </span>propertyChangedCallback, <span style="color: #2b91af">CoerceValueCallback </span>coerceValueCallback)</pre><a href="http://11011.net/software/vspaste"></a>
<p>依赖属性借用属性元数据的概念来完成属性默认值,属性通知,强制回调等行为</p>
<p><strong>1.属性默认值</strong></p><pre class="code"><span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>NameProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Name"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">string</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCustomPeople</span>), 
    <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(<span style="color: blue">string</span>.Empty));</pre>
<p>大部分人看到此处都会产生一个疑问,设置一个默认值为什么要用PropertyMetadata,为什么不直接在Register方法中直接注册呢?如下代码</p><pre class="code"><span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>NameProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Name"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">string</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCustomPeople</span>),
    <strike><span style="color: blue">string</span>.Empty</strike>);</pre>
<p>当然这个疑问一直伴随着我很久,解不开也是没办法,先放着.</p>
<p><strong>注意点:当在PropertyMetadata给属性赋默认值时,是无法检测类型正确性的</strong></p>
<p>如这样的定义,因为vs中的dp代码段默认值是0,这是值得注意的地方</p><pre class="code"><span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>NameProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Name"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">string</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCustomPeople</span>), 
    <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(0));</pre><a href="http://11011.net/software/vspaste"></a>
<p><strong>2.属性默认值恢复操作</strong></p>
<p>当属性赋值以后可以通过DependencyObject的ClearValue方法恢复默认值,如下代码</p><pre class="code"><span style="color: blue">public string </span>Name
{
    <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">string</span>)GetValue(NameProperty); }
    <span style="color: blue">set </span>{ SetValue(NameProperty, <span style="color: blue">value</span>); }
}

<span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>NameProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Name"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">string</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DPCustomPeople</span>), 
    <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(<span style="color: blue">string</span>.Empty));

<span style="color: blue">public void </span>DPPropertyClearOperator()
{
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Name:" </span>+ <span style="color: blue">this</span>.Name);
    <span style="color: blue">this</span>.Name=<span style="color: #a31515">"Terry"</span>;
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"ChangedName:" </span>+ <span style="color: blue">this</span>.Name);
    <span style="color: blue">this</span>.ClearValue(NameProperty);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Name:" </span>+ <span style="color: blue">this</span>.Name);
}</pre>
<p>输出结果</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_thumb_2.png" width="291" height="115"></a> </p>
<p><strong>注意点:区分默认赋值与默认值</strong></p>
<p>默认赋值一般在构造函数中进行,但这却不是默认值(在依赖属性出现之前这的确是),特别是在派生类重写属性的时候</p><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">Student </span>: <span style="color: #2b91af">DPCustomPeople
</span>{
    <span style="color: blue">public </span>Student()
    {
        <span style="color: blue">this</span>.Name = <span style="color: #a31515">"Sky"</span>;
    }

    <span style="color: blue">public void </span>TestSubDefaultDpValue()
    {
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Clear Before:"</span>+<span style="color: blue">this</span>.Name);
        <span style="color: blue">this</span>.ClearValue(<span style="color: #2b91af">Student</span>.NameProperty);
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Clear After:" </span>+ <span style="color: blue">this</span>.Name);
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>输出结果</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_10.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_thumb_4.png" width="278" height="93"></a> <a href="http://11011.net/software/vspaste"></a></p>
<p><strong>3.属性变更通知</strong></p>
<p>这项功能是最常用的.当属性值发生变化时,会触发<span style="color: #2b91af">PropertyChangedCallback</span>回调</p><pre class="code"><span style="color: blue">public bool </span>IsBoy
{
    <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">bool</span>)GetValue(IsBoyProperty); }
    <span style="color: blue">set </span>{ SetValue(IsBoyProperty, <span style="color: blue">value</span>); }
}

<span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>IsBoyProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"IsBoy"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">bool</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">Student</span>), 
    <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(<span style="color: blue">false</span>,<span style="color: blue">new </span><span style="color: #2b91af">PropertyChangedCallback</span>(IsBoyPropertyChangedCallback)));

<span style="color: blue">public static void </span>IsBoyPropertyChangedCallback(<span style="color: #2b91af">DependencyObject </span>d, <span style="color: #2b91af">DependencyPropertyChangedEventArgs </span>e)
{
    <span style="color: #2b91af">Student </span>st = d <span style="color: blue">as </span><span style="color: #2b91af">Student</span>;
    <span style="color: blue">if </span>(st.IsBoy)
    {
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Hello,Boy"</span>);
    }
    <span style="color: blue">else
    </span>{
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Hello,Girl"</span>);
    }
}

<span style="color: blue">public void </span>TestPropertyChangedCallback()
{
    <span style="color: blue">this</span>.IsBoy = <span style="color: blue">false</span>;
    <span style="color: blue">this</span>.IsBoy = <span style="color: blue">true</span>;<br><span style="color: blue">    this</span>.IsBoy = <span style="color: blue">true</span>; 
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>可以通过<strong>DependencyPropertyChangedEventArgs</strong>来查看旧值和新值<br>输出结果</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_12.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_thumb_5.png" width="289" height="92"></a> </p>
<p><strong>注意点:</strong></p>
<p>(1).通过上面的输出结果,你是否已经看出依赖属性的<strong>默认值是不会触发属性变更通知</strong>的</p>
<p>(2).<strong>手动触发属性变更通知</strong></p>
<p>如果你希望默认值也能触发一次属性变更(其实有时候真的需要),你就不等不手动进行触发了</p><pre class="code"><span style="color: blue">private void </span>RaiseIsBoyPropertyChangedCallback()
{
    IsBoyPropertyChangedCallback(<span style="color: blue">this</span>,<span style="color: blue">new </span><span style="color: #2b91af">DependencyPropertyChangedEventArgs
        </span>(<span style="color: #2b91af">Student</span>.IsBoyProperty, <span style="color: #2b91af">Student</span>.IsBoyProperty.DefaultMetadata.DefaultValue, <span style="color: blue">null</span>));
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>(3).<strong>当有属性变更通知时,一定要保证属性默认值类型的正确性</strong></p>
<p>我们知道值类型都有是默认值的,引用类型则没有(即可以赋值为null),一个类型是否有默认类型可以用default关键字查看.如下图</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_14.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_thumb_6.png" width="333" height="95"></a> </p>
<p>我们将上面定义的依赖属性默认值改写null,在没有<span style="color: #2b91af">PropertyChangedCallback</span>的时候可以很好的运行,但在有属性变更通知的时候灾难发生了,程序将出现异常,说类型不匹配.</p><pre class="code"><span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>IsBoyProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"IsBoy"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">bool</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">Student</span>), 
    <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(<span style="color: blue">null</span>,<span style="color: blue">new </span><span style="color: #2b91af">PropertyChangedCallback</span>(IsBoyPropertyChangedCallback)));</pre><a href="http://11011.net/software/vspaste"></a>
<p>再来看看引用类型,默认值为null则相安无事</p><pre class="code"><span style="color: blue">public </span><span style="color: #2b91af">IList </span>LovedGirl
{
    <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: #2b91af">IList</span>)GetValue(LovedGirlProperty); }
    <span style="color: blue">set </span>{ SetValue(LovedGirlProperty, <span style="color: blue">value</span>); }
}

<span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>LovedGirlProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"LovedGirl"</span>, <span style="color: blue">typeof</span>(<span style="color: #2b91af">IList</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">Student</span>),
    <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(<span style="color: blue">null</span>, <span style="color: blue">new </span><span style="color: #2b91af">PropertyChangedCallback</span>(LovedGirlChangedCallback)));

<span style="color: blue">public static void </span>LovedGirlChangedCallback(<span style="color: #2b91af">DependencyObject </span>d, <span style="color: #2b91af">DependencyPropertyChangedEventArgs </span>e)
{
    <span style="color: #2b91af">Student </span>st = d <span style="color: blue">as </span><span style="color: #2b91af">Student</span>;
    <span style="color: blue">foreach </span>(<span style="color: blue">var </span>item <span style="color: blue">in </span>e.NewValue <span style="color: blue">as </span><span style="color: #2b91af">IList</span>)
    {
        <span style="color: #2b91af">Console</span>.WriteLine(item);
    }
}

<span style="color: blue">public void </span>TestReferenceDpType()
{
    <span style="color: #2b91af">List</span>&lt;<span style="color: blue">string</span>&gt; list = <span style="color: blue">new </span><span style="color: #2b91af">List</span>&lt;<span style="color: blue">string</span>&gt;();
    list.Add(<span style="color: #a31515">"girl 1"</span>);
    list.Add(<span style="color: #a31515">"girl 2"</span>);
    <span style="color: blue">this</span>.LovedGirl = list;
}</pre>
<p><strong>4.强制属性回调</strong></p>
<p>首先默认值还是不会触发回调方法.</p>
<p>强制回调方法即不管属性值有无发生变化,都会进入回调方法</p><pre class="code"><span style="color: blue">public int </span>Score
{
    <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">int</span>)GetValue(ScoreProperty); }
    <span style="color: blue">set </span>{ SetValue(ScoreProperty, <span style="color: blue">value</span>); }
}

<span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>ScoreProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"Score"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">int</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">Student</span>), 
    <span style="color: blue">new </span><span style="color: #2b91af">UIPropertyMetadata</span>(0,<span style="color: blue">null</span>,<span style="color: blue">new </span><span style="color: #2b91af">CoerceValueCallback</span>(ScoreCoerceValueCallback)));

<span style="color: blue">public static object </span>ScoreCoerceValueCallback(<span style="color: #2b91af">DependencyObject </span>d, <span style="color: blue">object </span>baseValue)
{
    <span style="color: #2b91af">Console</span>.WriteLine(baseValue);
    <span style="color: blue">return </span>baseValue;
}

<span style="color: blue">public void </span>TestCoerceValueCallback()
{
    <span style="color: blue">this</span>.Score = 0;
    <span style="color: blue">this</span>.Score = 0;
    <span style="color: blue">this</span>.Score = 0;
}</pre><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_16.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf32_E539/image_thumb_7.png" width="285" height="118"></a> 
<p>&nbsp;</p>
<p>好了,本篇主要介绍了依赖属性的注册方法以及依赖属性的属性元数据用法.下篇继续</p>
<p><a href="http://cid-e61fe49e5e4bce66.skydrive.live.com/self.aspx/.Public/WPFCustomControlTutorial02/WPFControlTutorialPart3.rar">Demo下载</a></p><img src="http://www.cnblogs.com/Clingingboy/aggbug/1661370.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661370.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661370.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56819/" target="_blank">Yahoo脑震荡 关闭服务汇总贴</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56824/" target="_blank">2003年微软遭遇iTunes：我们彻底晕头转向了</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56823/" target="_blank">百度数据能被“作弊”软件篡改？百度:追究侵权</a><span style="color:gray">(2010-02-10 11:52)</span><br/>· <a href="http://news.cnblogs.com/n/56822/" target="_blank">Ksplice为Linux提供永远不用重启服务</a><span style="color:gray">(2010-02-10 11:51)</span><br/>· <a href="http://news.cnblogs.com/n/56821/" target="_blank">视频网站2010年格局之变：七成企业将被淘汰</a><span style="color:gray">(2010-02-10 11:48)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>wpf控件开发基础(2) -属性系统(1)</title><link>http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661090.html</link><dc:creator>Clingingboy</dc:creator><author>Clingingboy</author><pubDate>Mon, 01 Feb 2010 08:02:00 GMT</pubDate><guid>http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661090.html</guid><description><![CDATA[<p>阅读: 1193 评论: 2 作者: <a href="http://www.cnblogs.com/Clingingboy/" target="_blank">Clingingboy</a> 发表于 2010-02-01 16:02 <a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661090.html" target="_blank">原文链接</a></p><p>&nbsp;&nbsp;&nbsp;&nbsp; 距离上篇写的时间有1年多了.wpf太大,写的东西实在太多,我将依然围绕着自定义控件来展开与其相关的技术点. 也欢迎大家参与讨论.这篇我们将要讨论的是WPF依赖属性,接触过的朋友应该对其有所了解,但在我们讲WPF依赖属性之前,我们来看看在WPF出现之前.net中的属性是如何使用的.  <h2>普遍存在的属性问题</h2> <ul> <li>c#基本属性  <li>ASP.NET自定义控件属性  <li>WinForm自定义控件属性  <li>Javascript自定义控件属性 </li></ul> <p><strong>c#基本属性</strong>  <p></p><pre class="code"><span style="color: blue">namespace </span>WPFControlTutorialPart2_Basic
{
    <span style="color: blue">public class </span><span style="color: #2b91af">Person
    </span>{
        <span style="color: blue">private string </span>_name;
        <span style="color: blue">public string </span>Name
        {
            <span style="color: blue">get </span>{ <span style="color: blue">return </span>_name; }
            <span style="color: blue">set </span>{ _name = <span style="color: blue">value</span>; }
        }
        <span style="color: green">//自动属性
      </span><span style="color: blue">public int </span>Age { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    }
}
</pre><a href="http://11011.net/software/vspaste"></a>
<p>上面应该算是c#的最基础的属性,大家都很熟悉.</p>
<p><strong>注意点:默认属性没有初始化,不然可能会发生很多未知的错误.</strong></p>
<p><strong>(以下可以选看,如果你接触过以下技术的话,其实也很简单)</strong></p>
<p><strong>ASP.NET自定义控件属性</strong></p><pre class="code"><span style="color: blue">namespace </span>WPFControlTutorialPart2_WebApp
{
    <span style="color: blue">public class </span><span style="color: #2b91af">WebFromControl </span>: <span style="color: #2b91af">WebControl
    </span>{
        <span style="color: blue">private string </span>_controlName;
        <span style="color: blue">public string </span>ControlName
        {
            <span style="color: blue">get
            </span>{
                <span style="color: blue">return </span>_controlName;
            }
            <span style="color: blue">set
            </span>{
                _controlName = <span style="color: blue">value</span>;
            }
        }

        <span style="color: blue">protected override void </span>RenderContents(<span style="color: #2b91af">HtmlTextWriter </span>output)
        {
            output.Write(<span style="color: #a31515">"控件名字是:"</span>+ControlName);
        }
    }
}</pre>
<p><br>上面是一个简单的自定义的Web服务器控件.</p>
<p>asp.net控件着重在于呈现,每次刷新页面都将会调用RenderContents方法,这样就不管属性有没发生变化,都将得到重新呈现.即此处不需要属性发生变化,进行<strong>UI重绘通知.</strong></p>
<p><strong>注意点:如果强制要求ControlName属性必须是有值的,以保证输入结果的有效性,那么可以在get方法里处理</strong></p><pre class="code"><span style="color: blue">get
</span>{
    <span style="color: blue">if </span>(_controlName == <span style="color: blue">null</span>) _controlName = <span style="color: blue">string</span>.Empty;
    <span style="color: blue">return </span>_controlName;
}</pre><a href="http://11011.net/software/vspaste"></a>
<p><strong>WinForm自定义控件属性</strong></p>
<p>当属性发生变化时并未重绘,必须<strong>手动调用</strong>Invalidate方法以进入OnPaint方法重绘</p>
<p><strong>注意点:如果要重绘界面的话,必须手动调用方法</strong></p>
<p><strong>JavaScript自定义控件属性</strong></p><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">="demoDiv" </span><span style="color: red">style</span><span style="color: blue">="</span><span style="color: red">background-color</span>: <span style="color: blue">Red"&gt;</span>hello<span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;

&lt;</span><span style="color: #a31515">script</span><span style="color: blue">&gt;
    function </span>ElementControl(elementName) {
        <span style="color: blue">this</span>.element = document.getElementById(elementName);
    }
    ElementControl.prototype.setWidth = <span style="color: blue">function</span>(width) {
        <span style="color: blue">this</span>.element.style.width = width;
    }
    <span style="color: blue">var </span>obj = <span style="color: blue">new </span>ElementControl(<span style="color: #a31515">"demoDiv"</span>);
    obj.setWidth(<span style="color: #a31515">"hello"</span>);
   
<span style="color: blue">&lt;/</span><span style="color: #a31515">script</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a><br>javascript的变量类型没有强类型,比如设置dom的宽度,其类型只能是整型,如果以字符串进行传值的话将会出错(当然这是人为的).</p>
<p>(不知道做过js前端控件的人有没这种感觉,定义了一个属性然后重新赋值重绘控件是一件痛苦的事,必须手动调动,而且会影响整个控件设计.)</p>
<p><strong>注意点:要对于属性的赋值的有效性进行验证.<br></strong><strong><br>从以上几个例子,我们可以看出单纯的属性是无法满足程序需求的.<br>既以上的需求是有必要的,并且常常发生,而且非常频繁.</strong></p>
<h2>标准化解决方案<br></h2>
<p>以上介绍了属性存在的一系列问题,那么有问题就会有简化的方案.</p>
<p>以下是个人总结的话</p>
<ol>
<li><strong>当一项技术比较复杂的时候,就会有人出来定义一套标准,以简化技术,提高生产效率.</strong> 
<li><strong>不管设计者考虑的如何周密,一旦标准定义下来,就会丧失灵活性.</strong> 
<li><strong>标准可能与你个人习惯想冲突,你必须去学会接受标准</strong></li></ol>
<p><strong>回到WPF话题,那么在WPF中这个解决方案就是依赖属性(DependencyProperty)</strong></p>
<p><strong>好了,这篇只是一个引子,如果你在使用属性时,遇到过这些问题,那么你将有所感触.</strong></p>
<p><strong>如果你有认识到属性真实存在以上问题,那么这篇文章就算完成任务了.</strong></p>
<p><strong>这篇并不打算展开.下篇将再次介绍WPF依赖属性系统</strong></p>
<p><strong>欢迎大家展开讨论.</strong></p>
<p><a href="http://cid-e61fe49e5e4bce66.skydrive.live.com/browse.aspx/.Public/WPFCustomControlTutorial02">Demo下载</a></p><img src="http://www.cnblogs.com/Clingingboy/aggbug/1661090.html?type=1" width="1" height="1" alt=""/><p>评论: 2　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661090.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/02/01/1661090.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56819/" target="_blank">Yahoo脑震荡 关闭服务汇总贴</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56824/" target="_blank">2003年微软遭遇iTunes：我们彻底晕头转向了</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56823/" target="_blank">百度数据能被“作弊”软件篡改？百度:追究侵权</a><span style="color:gray">(2010-02-10 11:52)</span><br/>· <a href="http://news.cnblogs.com/n/56822/" target="_blank">Ksplice为Linux提供永远不用重启服务</a><span style="color:gray">(2010-02-10 11:51)</span><br/>· <a href="http://news.cnblogs.com/n/56821/" target="_blank">视频网站2010年格局之变：七成企业将被淘汰</a><span style="color:gray">(2010-02-10 11:48)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>MFC笔记(1)</title><link>http://www.cnblogs.com/Clingingboy/archive/2010/01/25/1655562.html</link><dc:creator>Clingingboy</dc:creator><author>Clingingboy</author><pubDate>Mon, 25 Jan 2010 01:03:00 GMT</pubDate><guid>http://www.cnblogs.com/Clingingboy/archive/2010/01/25/1655562.html</guid><description><![CDATA[<p>阅读: 94 评论: 0 作者: <a href="http://www.cnblogs.com/Clingingboy/" target="_blank">Clingingboy</a> 发表于 2010-01-25 09:03 <a href="http://www.cnblogs.com/Clingingboy/archive/2010/01/25/1655562.html" target="_blank">原文链接</a></p><p>&nbsp;&nbsp; 只为记忆更加深刻</p> <p>如果程序变的不是非常枯燥乏味,学的人就会有兴趣很多,学ui就是一种.虽然学ui只是起步,但足够增加对学习的信心,也为后续打下基础.</p> <p>有些人喜欢先探秘,比如先看深入浅出浅出MFC,我一直以来的想法是先学后用,如果连用都用不好，我想我也并不具备设计框架的能力.只有知道框架要做什么事情以后,自然自己心中会提出疑问.</p> <h2>Hello World程序</h2> <p>&nbsp;</p><pre class="code"><span style="color: green">// Define a window class derived from CFrameWnd
</span><span style="color: blue">class </span>CHelloWindow : <span style="color: blue">public </span>CFrameWnd
{
<span style="color: blue">public</span>:
    CHelloWindow()
        { Create(NULL, _T(<span style="color: #a31515">"Hello World!"</span>), WS_OVERLAPPEDWINDOW, rectDefault); }
};

<span style="color: blue">#endif

</span><span style="color: green">// Define an application class derived from CWinApp
</span><span style="color: blue">class </span>CHelloApp : <span style="color: blue">public </span>CWinApp
{
<span style="color: blue">public</span>:
    <span style="color: blue">virtual </span>BOOL InitInstance()
    {
        m_pMainWnd = <span style="color: blue">new </span>CHelloWindow();
        m_pMainWnd-&gt;ShowWindow(SW_SHOWNA);
        m_pMainWnd-&gt;UpdateWindow();
        <span style="color: blue">return </span>TRUE;
    }
};

CHelloApp HelloApp;  <span style="color: green">// HelloApp's constructor initializes and runs the app</span></pre>
<p><br>上面这段程序,实现了一个最简单的MFC程序,作为.net程序员,总是喜欢与.net中winfrom或者wpf进行比较.</p>
<p><strong>CFrameWnd</strong>可以理解为窗体的基类</p>
<p><strong>CWinApp</strong> 程序入口点,用于管理应用程序</p><pre><b>virtual BOOL</b> <b>Create(</b>
<b>   LPCTSTR</b> lpszClassName<b>,</b>
<b>   LPCTSTR</b> lpszWindowName<b>,</b>
<b>   DWORD</b> dwStyle <b>=</b> <b>WS_OVERLAPPEDWINDOW,</b>
<b>   const</b> <b>RECT&amp;</b> rect <b>=</b> <b>rectDefault,</b>
<b>   CWnd*</b> pParentWnd <b>=</b> <b>NULL,</b>
<b>   LPCTSTR</b> lpszMenuName <b>=</b> <b>NULL,</b>
<b>   DWORD</b> dwExStyle <b>=</b> <b>0,</b>
<b>   CCreateContext*</b> pContext <b>=</b> <b>NULL</b> 
<b>);</b></pre>
<p>一个最简单的窗体需要在构造函数中调用Create方法用于创建和初始化窗体的一些参数,即必须提供基本窗体参数,c++具备函数默认参数功能,所以最简单的只需要提供两个参数即可,其他参数随着时间的增长自然会熟悉,不需要去强记.</p>
<h2>c++风格的参数选择</h2>
<p><br>在c#中,习惯于使用枚举进行同一项的参数选择,但c++则喜欢定义常量,当然其实其他语言也这么做,相对而言,个人认为枚举的做法更加优雅.所以看c++程序需要接受这种风格,而且将会大量出现</p>
<h2>注意new</h2>
<h2>&nbsp;</h2>
<p>写c#程序new一个对象是非常正常的,c++的new就是申请内存,必须要删除掉的,没有GC,一看到new就要注意了。默认情况下,一个对象的初始化是不需要用new的，只需要声明,这是最大的区别,刚开始会看起来不习惯,看多了就好了，这是最大的注意点.</p>
<h2>初始化程序</h2>
<p><br>InitInstance方法提供了接口进行程序初始化,声明了一个窗体,并显示.</p><pre class="code">m_pMainWnd = <span style="color: blue">new </span>CHelloWindow();
m_pMainWnd-&gt;ShowWindow(SW_SHOWNA);
m_pMainWnd-&gt;UpdateWindow();</pre><a href="http://11011.net/software/vspaste"></a>
<p><br>ShowWindow用于设定窗体初始化的状态，并不是真正Show,奇怪为何不命名SetShowWindowState这样的方法,让人误解.来看下参数的定义,均是这种风格.不查文档或者不熟悉源码，基本就不知道他们的存在…如果改成枚举就可以SW.xxxx了.很厌恶…</p><pre class="code"><span style="color: green">/*
 * ShowWindow() Commands
 */
</span><span style="color: blue">#define </span>SW_HIDE             0
<span style="color: blue">#define </span>SW_SHOWNORMAL       1
<span style="color: blue">#define </span>SW_NORMAL           1
<span style="color: blue">#define </span>SW_SHOWMINIMIZED    2
<span style="color: blue">#define </span>SW_SHOWMAXIMIZED    3
<span style="color: blue">#define </span>SW_MAXIMIZE         3
<span style="color: blue">#define </span>SW_SHOWNOACTIVATE   4
<span style="color: blue">#define </span>SW_SHOW             5
<span style="color: blue">#define </span>SW_MINIMIZE         6
<span style="color: blue">#define </span>SW_SHOWMINNOACTIVE  7
<span style="color: blue">#define </span>SW_SHOWNA           8
<span style="color: blue">#define </span>SW_RESTORE          9
<span style="color: blue">#define </span>SW_SHOWDEFAULT      10
<span style="color: blue">#define </span>SW_FORCEMINIMIZE    11
<span style="color: blue">#define </span>SW_MAX              11</pre>
<p><br>UpdateWindow方法将会重绘窗体,呈现窗体.调用此方法将会触发ON_WM_PAINT消息.</p>
<p>注意c#很容易捕获一个事件,MFC与win32则称这些事件为消息，因为windows事件就是基于消息.所以两者概念上几乎是相同,说法不同,当然我更喜欢说事件.但不得不说消息:).</p>
<h2>消息映射</h2>
<p><br>在没有封装的情况下,默认捕获消息是用switch来判断的,很不方便,MFC通过消息映射机制来简化了这一操作.比如下面代码</p><pre class="code">BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd )
    <span style="color: green">//{{AFX_MSG_MAP( CMainWindow )
    </span>ON_WM_PAINT()
    <span style="color: green">//}}AFX_MSG_MAP
</span>END_MESSAGE_MAP()</pre>
<p><br>BEGIN_MESSAGE_MAP和END_MESSAGE_MAP用于声明消息的触发回调方法,(.net则更简单,直接重写即可)然后重写方法</p><pre class="code"><span style="color: blue">void </span>CMainWindow::OnPaint()
{
    CRect rect;
    GetClientRect(rect);

    CPaintDC dc(<span style="color: blue">this</span>);

    dc.DrawText (_T (<span style="color: #a31515">"Hello, MFC"</span>), -1, rect,
        DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    
}</pre><a href="http://11011.net/software/vspaste"></a><br>
<h2>&nbsp;</h2>
<p>以上用GDI在窗体中间画了一段文字</p>
<h2>对象获取方法</h2>
<p><br>在.net中若获取一个对象则,直接调函数返回,如 IList list=object.GetList();</p>
<p>到了c++这里则变成 IList list;GetLisht(&amp;list);这种风格也非常的多,这可能就是语言特性决定的做法.需要特别的注意.</p>
<p>&nbsp;</p>
<p>这样一个简单的MFC程序就完成了</p>
<p><a href="file:///C:/Users/Clingingboy/AppData/Local/Temp/WindowsLiveWriter-429641856/supfiles1C8851/image3.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="file:///C:/Users/Clingingboy/AppData/Local/Temp/WindowsLiveWriter-429641856/supfiles1C8851/image_thumb1.png" width="644" height="376"></a></p><img src="http://www.cnblogs.com/Clingingboy/aggbug/1655562.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/01/25/1655562.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/01/25/1655562.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56819/" target="_blank">Yahoo脑震荡 关闭服务汇总贴</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56824/" target="_blank">2003年微软遭遇iTunes：我们彻底晕头转向了</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56823/" target="_blank">百度数据能被“作弊”软件篡改？百度:追究侵权</a><span style="color:gray">(2010-02-10 11:52)</span><br/>· <a href="http://news.cnblogs.com/n/56822/" target="_blank">Ksplice为Linux提供永远不用重启服务</a><span style="color:gray">(2010-02-10 11:51)</span><br/>· <a href="http://news.cnblogs.com/n/56821/" target="_blank">视频网站2010年格局之变：七成企业将被淘汰</a><span style="color:gray">(2010-02-10 11:48)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>MFC笔记(2)菜单</title><link>http://www.cnblogs.com/Clingingboy/archive/2010/01/22/1654259.html</link><dc:creator>Clingingboy</dc:creator><author>Clingingboy</author><pubDate>Fri, 22 Jan 2010 08:00:00 GMT</pubDate><guid>http://www.cnblogs.com/Clingingboy/archive/2010/01/22/1654259.html</guid><description><![CDATA[<p>阅读: 80 评论: 0 作者: <a href="http://www.cnblogs.com/Clingingboy/" target="_blank">Clingingboy</a> 发表于 2010-01-22 16:00 <a href="http://www.cnblogs.com/Clingingboy/archive/2010/01/22/1654259.html" target="_blank">原文链接</a></p><p>&nbsp; 菜单以资源的形式出现,并以框架内置固定的位置出现</p> <p>首先在资源面板里创建菜单</p> <p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/MFC2_B6F6/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/MFC2_B6F6/image_thumb.png" width="495" height="157"></a> </p> <p>&nbsp;</p> <h2>载入菜单<br></h2> <p>1.在<strong>Create</strong>方法中传入菜单</p> <p>IDR_MAINFRAME为资源的Id,<strong>MAKEINTRESOURCE</strong>用于转换资源</p><pre class="code"><span style="color: blue">this</span>-&gt;Create(NULL,_T(<span style="color: #a31515">"Hello MFC"</span>),WS_POPUPWINDOW,rectDefault,NULL,<strong>MAKEINTRESOURCE(IDR_MAINFRAME)</strong>);</pre><a href="http://11011.net/software/vspaste"></a>
<p>2.也可以用<strong>LoadFrame</strong>方法载入资源并创建窗体,资源ID是可以重复的,若在字符串中定义IDR_MAINFRAME，则成为标题.</p>
<p><strong>注意:</strong>两方法不能同时使用,也不知道做了啥封装</p>
<p><strong>3.编程方式</strong></p><pre class="code">CMenu menu;
menu.LoadMenu(IDR_MAINFRAME);
SetMenu(&amp;menu);
menu.Detach();</pre>
<p><a href="http://11011.net/software/vspaste"></a><br>声明CMenu对象,然后手动根据ID号载入,然后调用SetMenu方法设置</p>
<p>4.重绘菜单</p>
<p>当有两个菜单的时候,替换的时候必须调用DrawMenuBar以重新绘制菜单</p><pre class="code">CMenu menu;
menu.LoadMenu(IDR_MENU1);
SetMenu(&amp;menu);
menu.Detach();
DrawMenuBar();</pre>
<p><a href="http://11011.net/software/vspaste"></a><br>5.菜单命令映射,用ON_COMMAND消息映射,ID_APP_ABOUT为菜单Id,OnAbout为对应的触发方法</p><pre class="code">ON_COMMAND(ID_APP_ABOUT, OnAbout)</pre>
<p><br>6.更新菜单项</p>
<p>可以用GetMenu方法当前选择的Menu,通过ON_UPDATE_COMMAND_UI消息映射,来更新菜单</p><img src="http://www.cnblogs.com/Clingingboy/aggbug/1654259.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/01/22/1654259.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Clingingboy/archive/2010/01/22/1654259.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56819/" target="_blank">Yahoo脑震荡 关闭服务汇总贴</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56824/" target="_blank">2003年微软遭遇iTunes：我们彻底晕头转向了</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56823/" target="_blank">百度数据能被“作弊”软件篡改？百度:追究侵权</a><span style="color:gray">(2010-02-10 11:52)</span><br/>· <a href="http://news.cnblogs.com/n/56822/" target="_blank">Ksplice为Linux提供永远不用重启服务</a><span style="color:gray">(2010-02-10 11:51)</span><br/>· <a href="http://news.cnblogs.com/n/56821/" target="_blank">视频网站2010年格局之变：七成企业将被淘汰</a><span style="color:gray">(2010-02-10 11:48)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>Caliburn笔记-Dependent Action(wpf框架)</title><link>http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1636244.html</link><dc:creator>Clingingboy</dc:creator><author>Clingingboy</author><pubDate>Wed, 30 Dec 2009 09:45:00 GMT</pubDate><guid>http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1636244.html</guid><description><![CDATA[<p>阅读: 135 评论: 0 作者: <a href="http://www.cnblogs.com/Clingingboy/" target="_blank">Clingingboy</a> 发表于 2009-12-30 17:45 <a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1636244.html" target="_blank">原文链接</a></p><p>&nbsp;&nbsp; <a href="http://caliburn.codeplex.com/wikipage?title=Dependent%20Actions&amp;referringTitle=Documentation">http://caliburn.codeplex.com/wikipage?title=Dependent%20Actions&amp;referringTitle=Documentation</a></p> <p>&nbsp;&nbsp; 这一部分功能也属于过滤器.再来看两个接口<br><br>FilterManager会在构造函数中,对实现该接口的Filter进行初始化</p><pre class="code"><span style="color: blue">public interface </span><span style="color: #2b91af">IInitializable </span>: <span style="color: #2b91af">IFilter
</span>{
    <span style="color: gray">/// &lt;summary&gt;
    /// </span><span style="color: green">Initializes the filter.
    </span><span style="color: gray">/// &lt;/summary&gt;
    /// &lt;param name="targetType"&gt;</span><span style="color: green">Type of the target.</span><span style="color: gray">&lt;/param&gt;
    /// &lt;param name="metadataContainer"&gt;</span><span style="color: green">The metadata container.</span><span style="color: gray">&lt;/param&gt;
    /// &lt;param name="serviceLocator"&gt;</span><span style="color: green">The serviceLocator.</span><span style="color: gray">&lt;/param&gt;
    </span><span style="color: blue">void </span>Initialize(<span style="color: #2b91af">Type </span>targetType, <span style="color: #2b91af">IMetadataContainer </span>metadataContainer, <span style="color: #2b91af">IServiceLocator </span>serviceLocator);
}</pre><a href="http://11011.net/software/vspaste"></a>
<p><br>&nbsp;</p><pre class="code"><span style="color: blue">public </span>FilterManager(<span style="color: #2b91af">Type </span>targetType, <span style="color: #2b91af">IMetadataContainer </span>metadataContainer, <span style="color: #2b91af">IServiceLocator </span>serviceLocator)
{
…
    filters.OfType&lt;<span style="color: #2b91af">IInitializable</span>&gt;()
        .Apply(x =&gt; x.Initialize(targetType, metadataContainer, serviceLocator));

…<br>}</pre>
<p><br>IHandlerAware用来实现对事件的监听</p><pre class="code"><span style="color: blue">public interface </span><span style="color: #2b91af">IHandlerAware </span>: <span style="color: #2b91af">IFilter
</span>{
    <span style="color: gray">/// &lt;summary&gt;
    /// </span><span style="color: green">Makes the filter aware of the </span><span style="color: gray">&lt;see cref="IRoutedMessageHandler"/&gt;</span><span style="color: green">.
    </span><span style="color: gray">/// &lt;/summary&gt;
    /// &lt;param name="messageHandler"&gt;</span><span style="color: green">The message handler.</span><span style="color: gray">&lt;/param&gt;
    </span><span style="color: blue">void </span>MakeAwareOf(<span style="color: #2b91af">IRoutedMessageHandler </span>messageHandler);

    <span style="color: gray">/// &lt;summary&gt;
    /// </span><span style="color: green">Makes the filter aware of the </span><span style="color: gray">&lt;see cref="IMessageTrigger"/&gt;</span><span style="color: green">.
    </span><span style="color: gray">/// &lt;/summary&gt;
    /// &lt;param name="messageHandler"&gt;</span><span style="color: green">The message handler.</span><span style="color: gray">&lt;/param&gt;
    /// &lt;param name="trigger"&gt;</span><span style="color: green">The trigger.</span><span style="color: gray">&lt;/param&gt;
    </span><span style="color: blue">void </span>MakeAwareOf(<span style="color: #2b91af">IRoutedMessageHandler </span>messageHandler, <span style="color: #2b91af">IMessageTrigger </span>trigger);
}</pre>
<p><br>如DependenciesAttribute的实现,<span style="color: #2b91af">DependencyObserver</span>对实现<span style="color: #2b91af">INotifyPropertyChanged</span>的对象进行了监听.</p><pre class="code"><span style="color: blue">public void </span>MakeAwareOf(<span style="color: #2b91af">IRoutedMessageHandler </span>messageHandler)
{
    <span style="color: blue">var </span>notifier = messageHandler.Unwrap() <span style="color: blue">as </span><span style="color: #2b91af">INotifyPropertyChanged</span>;
    <span style="color: blue">if </span>(notifier == <span style="color: blue">null</span>) <span style="color: blue">return</span>;

    <span style="color: blue">var </span>helper = messageHandler.GetMetadata&lt;<span style="color: #2b91af">DependencyObserver</span>&gt;();
    <span style="color: blue">if </span>(helper != <span style="color: blue">null</span>) <span style="color: blue">return</span>;

    helper = <span style="color: blue">new </span><span style="color: #2b91af">DependencyObserver</span>(messageHandler, notifier);
    messageHandler.AddMetadata(helper);
}</pre>
<p><br>然后在wpf元素初始化后,再次调用,添加事件</p><pre class="code"><span style="color: blue">public void </span>MakeAwareOf(<span style="color: #2b91af">IRoutedMessageHandler </span>messageHandler, <span style="color: #2b91af">IMessageTrigger </span>trigger)
{
    <span style="color: blue">var </span>helper = messageHandler.GetMetadata&lt;<span style="color: #2b91af">DependencyObserver</span>&gt;();
    <span style="color: blue">if </span>(helper == <span style="color: blue">null</span>) <span style="color: blue">return</span>;

    <span style="color: blue">if</span>(trigger.Message.RelatesTo(_target))
        helper.MakeAwareOf(trigger, _dependencies);
}</pre>
<p><br><span style="color: #2b91af">DependencyObserver</span>的MakeAwareOf.本质上海还是添加了MessageTrigger<br><br></p><pre class="code"><span style="color: blue">public void </span>MakeAwareOf(<span style="color: #2b91af">IMessageTrigger </span>trigger, <span style="color: #2b91af">IEnumerable</span>&lt;<span style="color: blue">string</span>&gt; dependencies)
{
    <span style="color: blue">foreach </span>(<span style="color: blue">var </span>dependency <span style="color: blue">in </span>dependencies)
    {
        <span style="color: #2b91af">IList</span>&lt;<span style="color: #2b91af">IMessageTrigger</span>&gt; triggers;
       
        <span style="color: blue">if</span>(!_triggersToNotify.TryGetValue(dependency, <span style="color: blue">out </span>triggers))
        {
            triggers = <span style="color: blue">new </span><span style="color: #2b91af">List</span>&lt;<span style="color: #2b91af">IMessageTrigger</span>&gt;();
            _triggersToNotify[dependency] = triggers;
        }       
        <span style="color: blue">if</span>(!triggers.Contains(trigger))
            triggers.Add(trigger);
    }
}</pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><img src="http://www.cnblogs.com/Clingingboy/aggbug/1636244.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1636244.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1636244.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56819/" target="_blank">Yahoo脑震荡 关闭服务汇总贴</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56824/" target="_blank">2003年微软遭遇iTunes：我们彻底晕头转向了</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56823/" target="_blank">百度数据能被“作弊”软件篡改？百度:追究侵权</a><span style="color:gray">(2010-02-10 11:52)</span><br/>· <a href="http://news.cnblogs.com/n/56822/" target="_blank">Ksplice为Linux提供永远不用重启服务</a><span style="color:gray">(2010-02-10 11:51)</span><br/>· <a href="http://news.cnblogs.com/n/56821/" target="_blank">视频网站2010年格局之变：七成企业将被淘汰</a><span style="color:gray">(2010-02-10 11:48)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>Caliburn笔记-过滤器管理(IFilterManager)(wpf框架)</title><link>http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635956.html</link><dc:creator>Clingingboy</dc:creator><author>Clingingboy</author><pubDate>Wed, 30 Dec 2009 05:40:00 GMT</pubDate><guid>http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635956.html</guid><description><![CDATA[<p>阅读: 114 评论: 0 作者: <a href="http://www.cnblogs.com/Clingingboy/" target="_blank">Clingingboy</a> 发表于 2009-12-30 13:40 <a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635956.html" target="_blank">原文链接</a></p><p>&nbsp;&nbsp;&nbsp;&nbsp; 过滤器用于装饰对象本身和对象中的方法.如下图</p> <p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/CaliburnIFilterManagerwpf_CF27/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/CaliburnIFilterManagerwpf_CF27/image_thumb.png" width="375" height="327"></a> </p> <p>具体介绍可见此</p> <p><a href="http://caliburn.codeplex.com/wikipage?title=Filters&amp;referringTitle=Documentation">http://caliburn.codeplex.com/wikipage?title=Filters&amp;referringTitle=Documentation</a></p> <h1>IFilterManager</h1> <p>IFilterManager接口为过滤器管理器,用于存放过滤器接口,每个Action都有一个过滤器管理器</p> <p> <h1>1.IRescue</h1> <p> 捕获错误<br></p><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">Calculator
</span>{

    [<span style="color: #2b91af">Rescue</span>(Priority=1)]
    <span style="color: blue">public int </span>Divide(<span style="color: blue">int </span>left, <span style="color: blue">int </span>right)
    {
        <span style="color: blue">throw new </span><span style="color: #2b91af">Exception</span>(<span style="color: #a31515">"error"</span>);
        <span style="color: blue">return </span>left / right;
    }
}</pre><a href="http://11011.net/software/vspaste"></a></p>
<h1>2.IPreProcessor</h1>
<p> 在Action触发之前触发或阻止Action触发</p>
<h1>3.IPostProcessor</h1>
<p>在Action触发之后触发</p><pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">PreProcessorAttribute </span>: <span style="color: #2b91af">Attribute</span>, <span style="color: #2b91af">IPreProcessor
   </span>{
       <span style="color: blue">#region </span>IPreProcessor Members

       <span style="color: blue">public bool </span>AffectsTriggers
       {
           <span style="color: blue">get </span>{ <span style="color: blue">return true</span>; }
       }

       <span style="color: blue">public bool </span>Execute(<span style="color: #2b91af">IRoutedMessage </span>message, <span style="color: #2b91af">IInteractionNode </span>handlingNode, <span style="color: blue">object</span>[] parameters)
       {
           <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"PreProcessor"</span>);
           <span style="color: blue">return true</span>;
       }

       <span style="color: blue">#endregion

       #region </span>IFilter Members

       <span style="color: blue">public int </span>Priority
       {
           <span style="color: blue">get </span>{ <span style="color: blue">return </span>1; }
       }

       <span style="color: blue">#endregion
   </span>}

   <span style="color: blue">public class </span><span style="color: #2b91af">PostProcessorAttribute </span>: <span style="color: #2b91af">Attribute</span>, <span style="color: #2b91af">IPostProcessor
   </span>{

       <span style="color: blue">#region </span>IPostProcessor Members

       <span style="color: blue">public void </span>Execute(<span style="color: #2b91af">IRoutedMessage </span>message, <span style="color: #2b91af">IInteractionNode </span>handlingNode, <span style="color: #2b91af">MessageProcessingOutcome </span>outcome)
       {
           <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"PostProcessor"</span>);
       }

       <span style="color: blue">#endregion

       #region </span>IFilter Members

       <span style="color: blue">public int </span>Priority { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }

       <span style="color: blue">#endregion
   </span>}</pre>
<p><a href="http://11011.net/software/vspaste"></a><br>看下执行结果</p><pre class="code">[<span style="color: #2b91af">PreProcessorAttribute</span>()]
[<span style="color: #2b91af">PostProcessorAttribute</span>()]
<span style="color: blue">public int </span>Divide(<span style="color: blue">int </span>left, <span style="color: blue">int </span>right)
{
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Action"</span>);
    <span style="color: blue">return </span>left / right;
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>&nbsp;</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/CaliburnIFilterManagerwpf_CF27/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/CaliburnIFilterManagerwpf_CF27/image_thumb_1.png" width="125" height="56"></a> </p>
<p>过滤器与Action是密切相关的,我们可以来看下Action内部的实现,看下面代码,上面的流程就非常的清晰了</p><pre class="code"><span style="color: blue">public override void </span>Execute(<span style="color: #2b91af">ActionMessage </span>actionMessage, <span style="color: #2b91af">IInteractionNode </span>handlingNode, <span style="color: blue">object </span>context)
{
    <span style="color: blue">try
    </span>{
        <span style="color: blue">var </span>parameters = _messageBinder.DetermineParameters(
            actionMessage,
            _requirements,
            handlingNode,
            context
            );

        <strike><span style="color: blue">foreach </span>(<span style="color: blue">var </span>filter <span style="color: blue">in </span>_filters.PreProcessors)</strike>
        {
            <span style="color: blue">if </span>(!filter.Execute(actionMessage, handlingNode, parameters)) <span style="color: blue">return</span>;
        }

        <span style="color: blue">var </span>outcome = <span style="color: blue">new </span><span style="color: #2b91af">MessageProcessingOutcome</span>(
           <strike> _method.Invoke(handlingNode.MessageHandler.Unwrap(), parameters),</strike>
            _method.Info.ReturnType,
            <span style="color: blue">false
            </span>);

       <strike> <span style="color: blue">foreach </span>(<span style="color: blue">var </span>filter <span style="color: blue">in </span>_filters.PostProcessors)</strike>
        {
            filter.Execute(actionMessage, handlingNode, outcome);
        }

        HandleOutcome(actionMessage, handlingNode, outcome);
    }
    <span style="color: blue">catch </span>(<span style="color: #2b91af">Exception </span>ex)
    {
      <strike>  <span style="color: blue">if</span>(!TryApplyRescue(actionMessage, handlingNode, ex))</strike>
            <span style="color: blue">throw</span>;
        OnCompleted();
    }
}</pre>
<p><br>可以使用以上特性定义自己需要的过滤器,建议不要重新定义Action,若要这么做的话就需要管理好过滤器的生命周期,或者有意更改生命周期</p><img src="http://www.cnblogs.com/Clingingboy/aggbug/1635956.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635956.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635956.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56819/" target="_blank">Yahoo脑震荡 关闭服务汇总贴</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56824/" target="_blank">2003年微软遭遇iTunes：我们彻底晕头转向了</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56823/" target="_blank">百度数据能被“作弊”软件篡改？百度:追究侵权</a><span style="color:gray">(2010-02-10 11:52)</span><br/>· <a href="http://news.cnblogs.com/n/56822/" target="_blank">Ksplice为Linux提供永远不用重启服务</a><span style="color:gray">(2010-02-10 11:51)</span><br/>· <a href="http://news.cnblogs.com/n/56821/" target="_blank">视频网站2010年格局之变：七成企业将被淘汰</a><span style="color:gray">(2010-02-10 11:48)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>Caliburn笔记-依赖注入容器(wpf框架)</title><link>http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635800.html</link><dc:creator>Clingingboy</dc:creator><author>Clingingboy</author><pubDate>Wed, 30 Dec 2009 03:10:00 GMT</pubDate><guid>http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635800.html</guid><description><![CDATA[<p>阅读: 135 评论: 0 作者: <a href="http://www.cnblogs.com/Clingingboy/" target="_blank">Clingingboy</a> 发表于 2009-12-30 11:10 <a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635800.html" target="_blank">原文链接</a></p><p>参考与此<a href="http://caliburn.codeplex.com/wikipage?title=Auto-Registering%20Components&amp;referringTitle=Documentation">http://caliburn.codeplex.com/wikipage?title=Auto-Registering%20Components&amp;referringTitle=Documentation</a></p> <p>&nbsp;&nbsp;&nbsp; 此为基础,看了没用,不看不行…了解下注册流程.</p> <p><br>注册组件,差不多离不开这几种模式</p> <ol> <li>手动注册  <li>元数据标签注册  <li>外部dll加载注册</li></ol> <p>1.内置服务则用手动注册.</p> <p>2.挂元数据标签,如下</p><pre class="code">[<span style="color: #2b91af">PerRequest</span>(<span style="color: blue">typeof</span>(<span style="color: #2b91af">IHomePresenter</span>))]
<span style="color: blue">public class </span><span style="color: #2b91af">HomePresenter </span>: <span style="color: #2b91af">Presenter</span>, <span style="color: #2b91af">IHomePresenter
</span>{
}</pre>
<p><br>以前不是推荐此种做法的,标签会产生框架耦合,但框架用都用了，内置demo使用此方法最多,之前用的是手动注册,框架会去dll中寻找挂此标签的对象然后自动注册.</p>
<p>3.外部dll加载</p>
<p>重写CaliburnApplication的SelectAssemblies方法</p><pre class="code"><span style="color: blue">protected override </span>System.Reflection.<span style="color: #2b91af">Assembly</span>[] SelectAssemblies()
{
    <span style="color: blue">return new</span>[] { <span style="color: #2b91af">Assembly</span>.GetEntryAssembly(),<span style="color: blue">typeof</span>(Caliburn.WPF.ApplicationFramework.<span style="color: #2b91af">Bind</span>).Assembly};
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>&nbsp;</p><pre class="code"><span style="color: blue">private void </span>InspectAssembly(<span style="color: #2b91af">Assembly </span>assembly, <span style="color: #2b91af">ICollection</span>&lt;<span style="color: #2b91af">ComponentInfo</span>&gt; componentList, <span style="color: #2b91af">ICollection</span>&lt;<span style="color: #2b91af">Type</span>&gt; configs)
{
    <span style="color: blue">var </span>types = assembly.GetExportedTypes();

    <span style="color: blue">foreach </span>(<span style="color: blue">var </span>type <span style="color: blue">in </span>types)
    {
        <span style="color: blue">foreach </span>(<span style="color: blue">var </span>attribute <span style="color: blue">in </span>type.GetCustomAttributes(<span style="color: blue">true</span>).OfType&lt;<span style="color: #2b91af">RegisterAttribute</span>&gt;())
            componentList.Add(attribute.GetComponentInfo(type));
    }

    <span style="color: blue">foreach </span>(<span style="color: blue">var </span>type <span style="color: blue">in </span>types)
    {
        <span style="color: blue">if</span>(_configType.IsAssignableFrom(type) &amp;&amp; !type.IsAbstract)
            configs.Add(type);
    }
}</pre>
<p><br>总的来说，我们只要加载dll，挂上标签就可以自动注册了</p>
<p>内置服务+自定义服务注册好以后,接下来的任务就是注册实例.即组件的生命周期状况.内置都为Singleton</p><pre class="code"><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">The lifetime of a Caliburn component.
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">public enum </span><span style="color: #2b91af">ComponentLifetime
</span>{
    <span style="color: gray">/// &lt;summary&gt;
    /// </span><span style="color: green">One instance per application.
    </span><span style="color: gray">/// &lt;/summary&gt;
    </span>Singleton,
    <span style="color: gray">/// &lt;summary&gt;
    /// </span><span style="color: green">A new instance is created on each request.
    </span><span style="color: gray">/// &lt;/summary&gt;
    </span>PerRequest,
    <span style="color: gray">/// &lt;summary&gt;
    /// </span><span style="color: green">A new instance is created per custom lifetime rules.
    </span><span style="color: gray">/// &lt;/summary&gt;
    </span>Custom
}</pre>
<p><br>可以通过重写ConfigureWith方法,使用第三方容器来注册服务,当然其内置也提供了一个较为简单的容器</p>
<p>新版本可能会更新,所以不去研究它了</p><img src="http://www.cnblogs.com/Clingingboy/aggbug/1635800.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635800.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635800.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56819/" target="_blank">Yahoo脑震荡 关闭服务汇总贴</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56824/" target="_blank">2003年微软遭遇iTunes：我们彻底晕头转向了</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56823/" target="_blank">百度数据能被“作弊”软件篡改？百度:追究侵权</a><span style="color:gray">(2010-02-10 11:52)</span><br/>· <a href="http://news.cnblogs.com/n/56822/" target="_blank">Ksplice为Linux提供永远不用重启服务</a><span style="color:gray">(2010-02-10 11:51)</span><br/>· <a href="http://news.cnblogs.com/n/56821/" target="_blank">视频网站2010年格局之变：七成企业将被淘汰</a><span style="color:gray">(2010-02-10 11:48)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>Caliburn笔记-Action简写(wpf框架)</title><link>http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635757.html</link><dc:creator>Clingingboy</dc:creator><author>Clingingboy</author><pubDate>Wed, 30 Dec 2009 02:29:00 GMT</pubDate><guid>http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635757.html</guid><description><![CDATA[<p>阅读: 108 评论: 0 作者: <a href="http://www.cnblogs.com/Clingingboy/" target="_blank">Clingingboy</a> 发表于 2009-12-30 10:29 <a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635757.html" target="_blank">原文链接</a></p><p><br><a href="http://caliburn.codeplex.com/wikipage?title=Action%20Basics&amp;referringTitle=Documentation">http://caliburn.codeplex.com/wikipage?title=Action%20Basics&amp;referringTitle=Documentation</a></p><pre class="code"><span style="color: blue">public void </span>Demo()
{
    <span style="color: #2b91af">MessageBox</span>.Show(<span style="color: #a31515">"hello"</span>);
}</pre><a href="http://11011.net/software/vspaste"></a>
<h1>1.传递方法</h1><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">Button </span><span style="color: red">Content</span><span style="color: blue">="Demo"
        </span><span style="color: red">cal</span><span style="color: blue">:</span><span style="color: red">Message.Attach</span><span style="color: blue">="Demo" /&gt;</span></pre><a href="http://11011.net/software/vspaste"></a><br>
<h1>2.使用事件传递<br><br>(1)</h1><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">Button </span><span style="color: red">Content</span><span style="color: blue">="Demo"
        </span><span style="color: red">cal</span><span style="color: blue">:</span><span style="color: red">Message.Attach</span><span style="color: blue">="[Event Click] = [Action Demo]" /&gt;</span></pre>
<p>&nbsp;</p>
<h1>(2)附加事件(好像有bug)</h1><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">StackPanel </span><span style="color: red">cal</span><span style="color: blue">:</span><span style="color: red">Message.Attach</span><span style="color: blue">="[AttachedEvent Button.Click] = [Action Demo]"&gt;
    &lt;</span><span style="color: #a31515">Button </span><span style="color: red">Content</span><span style="color: blue">="Divide (Stack)" /&gt;
    &lt;</span><span style="color: #a31515">Button </span><span style="color: red">Content</span><span style="color: blue">="Divide (Stack)" /&gt;
&lt;/</span><span style="color: #a31515">StackPanel</span><span style="color: blue">&gt;</span><br></pre>
<h1>3.事件连写(分号相隔)</h1><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">Button </span><span style="color: red">Content</span><span style="color: blue">="Demo"
        </span><span style="color: red">cal</span><span style="color: blue">:</span><span style="color: red">Message.Attach</span><span style="color: blue">="[Event Click] = [Action Demo];[Event Loaded] = [Action Demo]" /&gt;</span></pre><br>
<h1>其他事件请参考此处</h1>
<p><a href="http://caliburn.codeplex.com/wikipage?title=Message%20Triggers&amp;referringTitle=Documentation">http://caliburn.codeplex.com/wikipage?title=Message%20Triggers&amp;referringTitle=Documentation</a></p>
<h1>4.参数传递<br><br>(1)</h1><pre class="code"><span style="color: blue">public void </span>Demo(<span style="color: blue">string </span>str)
{
    <span style="color: #2b91af">MessageBox</span>.Show(str);
}</pre><a href="http://11011.net/software/vspaste"></a><br><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">Button </span><span style="color: red">Content</span><span style="color: blue">="Demo"
        </span><span style="color: red">cal</span><span style="color: blue">:</span><span style="color: red">Message.Attach</span><span style="color: blue">="Demo('hello')" /&gt;</span></pre>
<h1>(2)支持元素对象获取</h1><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">TextBox </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">="demoBox" /&gt;
&lt;</span><span style="color: #a31515">Button </span><span style="color: red">Content</span><span style="color: blue">="Demo"
        </span><span style="color: red">cal</span><span style="color: blue">:</span><span style="color: red">Message.Attach</span><span style="color: blue">="Demo(demoBox.Text)" /&gt;</span></pre><br>
<h1>(3)支持内置参数解析</h1><a href="http://caliburn.codeplex.com/wikipage?title=Parameters&amp;referringTitle=Documentation">http://caliburn.codeplex.com/wikipage?title=Parameters&amp;referringTitle=Documentation</a><br><br><pre class="code"><span style="color: blue">public void </span>Demo(<span style="color: blue">object </span>sender,<span style="color: #2b91af">EventArgs </span>args)
{
   
}</pre><a href="http://11011.net/software/vspaste"></a><br><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">Button </span><span style="color: red">Content</span><span style="color: blue">="Demo"
        </span><span style="color: red">cal</span><span style="color: blue">:</span><span style="color: red">Message.Attach</span><span style="color: blue">="Demo($source,$eventArgs)" /&gt;</span></pre><a href="http://11011.net/software/vspaste"></a><br>
<h1>(4)支持返回值传递</h1><pre class="code"><span style="color: blue">public int </span>Demo()
{
    <span style="color: blue">return </span>1;
}</pre><a href="http://11011.net/software/vspaste"></a><br><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">TextBox </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">="demoBox" /&gt;
&lt;</span><span style="color: #a31515">Button </span><span style="color: red">Content</span><span style="color: blue">="Demo"
        </span><span style="color: red">cal</span><span style="color: blue">:</span><span style="color: red">Message.Attach</span><span style="color: blue">="[Action Demo : demoBox.Text]" /&gt;</span></pre><a href="http://11011.net/software/vspaste"></a><br>
<h1>(5)支持绑定模式</h1><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">TextBox </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">="demoBox" /&gt;
&lt;</span><span style="color: #a31515">Button </span><span style="color: red">Content</span><span style="color: blue">="Demo"
        </span><span style="color: red">cal</span><span style="color: blue">:</span><span style="color: red">Message.Attach</span><span style="color: blue">="[Action Demo(demoBox.Text:TwoWay)]" /&gt;</span></pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a><img src="http://www.cnblogs.com/Clingingboy/aggbug/1635757.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635757.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Clingingboy/archive/2009/12/30/1635757.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56819/" target="_blank">Yahoo脑震荡 关闭服务汇总贴</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56824/" target="_blank">2003年微软遭遇iTunes：我们彻底晕头转向了</a><span style="color:gray">(2010-02-10 12:06)</span><br/>· <a href="http://news.cnblogs.com/n/56823/" target="_blank">百度数据能被“作弊”软件篡改？百度:追究侵权</a><span style="color:gray">(2010-02-10 11:52)</span><br/>· <a href="http://news.cnblogs.com/n/56822/" target="_blank">Ksplice为Linux提供永远不用重启服务</a><span style="color:gray">(2010-02-10 11:51)</span><br/>· <a href="http://news.cnblogs.com/n/56821/" target="_blank">视频网站2010年格局之变：七成企业将被淘汰</a><span style="color:gray">(2010-02-10 11:48)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56812/" target="_blank">Google社会化产品Buzz发布会实录</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item></channel></rss>