1. 什么是附加属性 (attached property)
附加属性依赖属性的一种特殊形式, 常见的 Grid.Row,Canvas.Left 都是附加属性
- /// <summary>
- // 从指定元素获取 Left 依赖项属性的值
- /// </summary>
- /// <param name="obj">The element from which the property value is read.</param>
- /// <returns>Left 依赖项属性的值 </returns>
- public static double GetLeft(DependencyObject obj)
- {
- return (double)obj.GetValue(LeftProperty);
- }
- /// <summary>
- /// 将 Left 依赖项属性的值设置为指定元素
- /// </summary>
- /// <param name="obj">The element on which to set the property value.</param>
- /// <param name="value">The property value to set.</param>
- public static void SetLeft(DependencyObject obj, double value)
- {
- obj.SetValue(LeftProperty, value);
- }
- /// <summary>
- /// 标识 Left 依赖项属性
- /// </summary>
- public static readonly DependencyProperty LeftProperty =
- DependencyProperty.RegisterAttached("Left", typeof(double), typeof(MyCanvas), new PropertyMetadata(0d));
附加属性的简单定义如上述代码所示可以看出和依赖属性不同的地方在于没有作为属性包装器的 Setter 和 Getter, 而多了两个静态函数 GetXXX 和 SetXXX 并且注册标识符使用 DependencyProperty.RegisterAttached 而不是 DependencyProperty.Register
2. 附加属性有什么作用
和依赖属性不同的地方在于, 依赖属性是依赖对象本身的属性, 附加属性是附加在其他对象身上的属性, 通俗来说就是在别的对象内插入自己的属性上面提到的 Grid.Row, 就是 Grid 将 Row 属性附加到没有 Row 属性的其它类中, 以便进行布局
3. 附加属性的使用
附加实行的使用方式和依赖属性十分相似
在 XAML 中使用附加属性:
<StackPanel Grid.Row="1"/>
在 C# 代码中使用附加属性:
button.SetValue(Grid.RowProperty, 1);
4. 完整的自定义附加属性
- /// <summary>
- // 从指定元素获取 Left 依赖项属性的值
- /// </summary>
- /// <param name="obj">The element from which the property value is read.</param>
- /// <returns>Left 依赖项属性的值 </returns>
- public static double GetLeft(DependencyObject obj)
- {
- return (double)obj.GetValue(LeftProperty);
- }
- /// <summary>
- /// 将 Left 依赖项属性的值设置为指定元素
- /// </summary>
- /// <param name="obj">The element on which to set the property value.</param>
- /// <param name="value">The property value to set.</param>
- public static void SetLeft(DependencyObject obj, double value)
- {
- obj.SetValue(LeftProperty, value);
- }
- /// <summary>
- /// 标识 Left 依赖项属性
- /// </summary>
- public static readonly DependencyProperty LeftProperty =
- DependencyProperty.RegisterAttached("Left", typeof(double), typeof(MyCanvas), new PropertyMetadata(0d, OnLeftChanged));
- private static void OnLeftChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
- {
- double oldValue = (double)args.OldValue;
- double newValue = (double)args.NewValue;
- if (oldValue == newValue)
- return;
- }
以上代码为一个相对完整的自定义附加属性, 自定义附加属性的步骤如下
1. 使用 DependencyProperty.RegisterAttached 注册附加属性标识符, 标示符的名称必须是 PropertyName+Property, 如这个例子中的 LeftProperty 在 PropertyMetadata 中指定属性默认值
实现静态的属性访问器函数, 名称必须是 GetPropertyName 和 SetPropertyName, 如例子中的 public static double GetLeft(DependencyObject obj) 和 public static void SetLeft(DependencyObject obj, double value)
如果需要监视属性值变更, 可以在 PropertyMetadata 中定义一个 PropertyChangedCallback 方法, 一遍命名方式为 OnPropertyNameChanged, 如上述例子中的 private static void OnLeftChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
注意: 属性访问器中不要有多余的代码, 理由参考依赖属性
VisualStudio 自带附加属性的代码段是 propa, 生成代码如下:
- public static int GetMyProperty(DependencyObject obj)
- {
- return (int)obj.GetValue(MyPropertyProperty);
- }
- public static void SetMyProperty(DependencyObject obj, int value)
- {
- obj.SetValue(MyPropertyProperty, value);
- }
- // Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
- public static readonly DependencyProperty MyPropertyProperty =
- DependencyProperty.RegisterAttached("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0));
要生成上述例子的完整附加属性代码, 可使用自定义的代码段, 快捷键是 ap:
- <?xml version="1.0" encoding="utf-8"?>
- <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
- <CodeSnippet Format="1.0.0">
- <Header>
- <Keywords>
- <Keyword>ap</Keyword>
- </Keywords>
- <SnippetTypes>
- <SnippetType>Expansion</SnippetType>
- </SnippetTypes>
- <Title>Attached Property</Title>
- <Author>dino.c</Author>
- <Description>For Attached Property</Description>
- <HelpUrl>
- </HelpUrl>
- <Shortcut>ap</Shortcut>
- </Header>
- <Snippet>
- <References>
- <Reference>
- <Assembly>
- </Assembly>
- </Reference>
- </References>
- <Declarations>
- <Literal Editable="true">
- <ID>int</ID>
- <ToolTip>int</ToolTip>
- <Default>int</Default>
- <Function>
- </Function>
- </Literal>
- <Literal Editable="true">
- <ID>MyProperty</ID>
- <ToolTip > 属性名 </ToolTip>
- <Default>MyProperty</Default>
- <Function>
- </Function>
- </Literal>
- <Literal Editable="false">
- <ID>classname</ID>
- <ToolTip > 类名 </ToolTip>
- <Function>ClassName()</Function>
- <Default>ClassNamePlaceholder</Default>
- </Literal>
- </Declarations>
- <Code Language="csharp">
- <![CDATA[
- /// <summary>
- // 从指定元素获取 $MyProperty$ 依赖项属性的值
- /// </summary>
- /// <param name="obj">The element from which the property value is read.</param>
- /// <returns>$MyProperty$ 依赖项属性的值 </returns>
- public static $int$ Get$MyProperty$(DependencyObject obj)
- {
- return ($int$)obj.GetValue($MyProperty$Property);
- }
- /// <summary>
- /// 将 $MyProperty$ 依赖项属性的值设置为指定元素
- /// </summary>
- /// <param name="obj">The element on which to set the property value.</param>
- /// <param name="value">The property value to set.</param>
- public static void Set$MyProperty$(DependencyObject obj, $int$ value)
- {
- obj.SetValue($MyProperty$Property, value);
- }
- /// <summary>
- /// 标识 $MyProperty$ 依赖项属性
- /// </summary>
- public static readonly DependencyProperty $MyProperty$Property =
- DependencyProperty.RegisterAttached("$MyProperty$", typeof($int$), typeof($classname$), new PropertyMetadata(0,On$MyProperty$Changed));
- private static void On$MyProperty$Changed(DependencyObject obj, DependencyPropertyChangedEventArgs args)
- {
- $classname$ target = obj as $classname$;
- $int$ oldValue = ($int$)args.OldValue;
- $int$ newValue = ($int$)args.NewValue;
- if (oldValue == newValue)
- return;
- }
- ]]>
- </Code>
- </Snippet>
- </CodeSnippet>
- </CodeSnippets>
来源: http://blog.csdn.net/cjh623/article/details/79632913