1. 程式人生 > >WPF QuickStart系列之附加屬性(Attached Property)

WPF QuickStart系列之附加屬性(Attached Property)

原文: WPF QuickStart系列之附加屬性(Attached Property)

這一篇部落格是關於如何使用附加屬性和建立自定義附加屬性的。

1. 附加屬性使用,

WPF中對附加屬性使用最多的莫過於對控制元件佈局時設定控制元件的位置,例如在Canvas中有一個Rectangle, Ellipse, Button,我們需要設定它們的位置,

    <Canvas>
        <Rectangle x:Name="_rect" Fill="LightBlue" Width="100" Height="50" Canvas.Left="200" Canvas.Top="50"
/> <Ellipse Width="100" Height="100" Fill="LightCoral" Canvas.Left="150" Canvas.Top="200"/> <Button Content="I am a button" Width="100" Height="35" Canvas.Left="50" Canvas.Bottom="50"/> </Canvas>

除了在XAML中設定依賴屬性外,也可以在C#程式碼中設定,例如:

   Canvas.SetLeft(_rect, 100
); Canvas.SetTop(_rect, 50);

顯示效果:

附加屬性使用起來非常簡單。

2. 自定義附加屬性

現在有這樣一個需求,需要將上面的Button,Ellipse,Rectangle旋轉一定角度。我們可以這樣來實現:

XAML:

    <Canvas>
        <Rectangle x:Name="_rect" Fill="LightBlue" Width="100" Height="50" Canvas.Top="100" RenderTransformOrigin=".5,.5">
            <
Rectangle.RenderTransform> <RotateTransform Angle="45"/> </Rectangle.RenderTransform> </Rectangle> <Ellipse Width="150" Height="100" Fill="LightCoral" Canvas.Left="150" Canvas.Top="100" RenderTransformOrigin=".5,.5"> <Ellipse.RenderTransform> <RotateTransform Angle="60"/> </Ellipse.RenderTransform> </Ellipse> <Button Content="I am a button" Width="100" Height="35" Canvas.Left="50" Canvas.Bottom="50" RenderTransformOrigin=".5,.5"> <Button.RenderTransform> <RotateTransform Angle="160"/> </Button.RenderTransform> </Button> </Canvas>

效果如下:

 

細心的你已經發現上面的三段程式碼基本一樣,而且還挺長的。我們可以使用附加屬性來實現,新建一個RotationHelper類,程式碼如下:

using System.Windows;
using System.Windows.Media;

namespace UseAttachedProperty.Helper
{
    public class RotationHelper : DependencyObject
    {
        public static double GetAngle(DependencyObject obj)
        {
            return (double)obj.GetValue(AngleProperty);
        }

        public static void SetAngle(DependencyObject obj, double value)
        {
            obj.SetValue(AngleProperty, value);
        }

        public static readonly DependencyProperty AngleProperty =
            DependencyProperty.RegisterAttached("AngleProperty", typeof(double), typeof(RotationHelper), 
                new PropertyMetadata(0.0,OnAngleChanged));

        private static void OnAngleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement element = d as UIElement;

            if(element != null)
            {
                element.RenderTransformOrigin = new Point(0.5, 0.5);
                element.RenderTransform = new RotateTransform((double)e.NewValue);
            }
        }
    }
}

將RotationHelper類繼承DependencyObject,這樣不光Button,Ellipse,可以使用,其他繼承自DependencyObject的元素均可使用。

現在在XAML中使用自定義Angle附加屬性。

<Window x:Class="UseAttachedProperty.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:helper="clr-namespace:UseAttachedProperty.Helper"
        xmlns:local="clr-namespace:UseAttachedProperty"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Canvas>
        <Rectangle x:Name="_rect" Fill="LightBlue" Width="100" Height="50" Canvas.Top="100" helper:RotationHelper.Angle="45" />

        <Ellipse Width="150" Height="100" Fill="LightCoral" Canvas.Left="150" Canvas.Top="100" helper:RotationHelper.Angle="60" />

        <Button Content="I am a button" Width="100" Height="35" Canvas.Left="50" Canvas.Bottom="50" helper:RotationHelper.Angle="160" />
    </Canvas>
</Window>

此時顯示效果和上面通過XAML中使用RenderTransform一樣。

感謝您的閱讀。程式碼點選這裡下載。

PS:目前在工作中,

1. 給TextBox和PasswordBox設定水印文字時,使用到自定義附加屬性,示例程式碼下載

2. 在WPF MVVM模式下,需要直接繫結PasswordBox的Password屬性時是不可以的,因為Password屬性不是依賴屬性,此時使用自定義附加屬性解決了這個問題。示例程式碼下載