WPF整理-爲控件添加自定義附加屬性

附加屬性

附加屬性,你們都不陌生,最多見的是Canvas.Left/Canvas.Top,相似的也有Grid.Row/Grid.Column等附加屬性。舉個最多見的例子html

<Canvas>
   <Ellipse Fill="Red" Width="100" Height="60" Canvas.Left="56" Canvas.Top="98"/>
</Canvas>

須要說明的是並非全部的附加屬性都是元素放進去後纔會有附加效果,上面的例子只是恰好是這種錯覺的巧合狀況,Grid.Row也屬於這種巧合。
仍是舉個反例來講明編輯器

<Canvas>
   <Button Content="Copy" ToolTip="Copy the Selected Items"ToolTipService.ShowOnDisabled="True"/>
</Canvas>

ToolTipService類是一個靜態類,和Button風馬牛不相及,二者之間沒有任何關係。ide

這就是關於附加屬性DebugLZQ認爲須要說明的地方。post

爲控件添加一個自定義的附加屬性

1.咱們有這樣的一個XAMLurl

    <Canvas>
        <Ellipse Fill="Red" Width="100" Height="60" />
        <Rectangle Fill="Blue" Width="80" Height="80" Canvas.Left="100" Canvas.Top="100" />
        <Button Content="Hello" Canvas.Left="130" Canvas.Top="30" FontSize="20" />
    </Canvas>

假如,咱們須要實現控件繞中心旋轉必定的角度。一般咱們須要寫相似的Rotatespa

        <Ellipse Fill="Red" Width="100" Height="60" RenderTransformOrigin=".5,.5">
            <Ellipse.RenderTransform>
                <RotateTransform Angle="30" />
            </Ellipse.RenderTransform>
        </Ellipse>

固然這樣OK,程序運行沒有問題。
但,缺點是須要寫較多的代碼;當咱們須要爲頁面其餘全部元素實現旋轉時,又須要寫大量相似的代碼。code

咱們能夠經過附加屬性來簡化代碼。如何作呢?orm

2.爲工程添加一個名爲RotationManager的類,咱們在這個類中添加一個附加屬性,讓其餘都能使用這個附加屬性。xml

咱們在類中鍵入"propa"htm

和依賴屬性相似,連按2次Tab,修改相應命名,以下:

        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("Angle", typeof(double), typeof(RotationManager), new PropertyMetadata(0.0));

這樣咱們就完成了附加屬性的定義。
爲了可以在XAML中使用,在XAML中添加以下映射。

<Window x:Class="CreatingAnAttachedProperty.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CreatingAnAttachedProperty"

這樣,頁面上的元素就可使用這個附加屬性了,以下:

    <Canvas>
        <Ellipse Fill="Red" Width="100" Height="60" Canvas.Left="56" Canvas.Top="98" local:RotationManager.Angle="30"/>
        <Rectangle Fill="Blue" Width="80" Height="80" Canvas.Left="285" Canvas.Top="171" local:RotationManager.Angle="45" />
        <Button Content="Hello" Canvas.Left="265" Canvas.Top="48" FontSize="20" local:RotationManager.Angle="60"/>        
    </Canvas>

3.此時編輯器,沒有任何旋轉,若咱們此時運行程序,也沒有任何的旋轉效果,爲何?由於咱們只是添加了一個附加屬性,給它付了個初值,當值改變的時候,咱們並無添加相應的處理邏輯。
依次,咱們須要返回RotationManager.cs添加相應的值改變事件及事件處理邏輯。以下:

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

        private static void OnAngleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as UIElement;
            if (element != null)
            {
                element.RenderTransformOrigin = new Point(0.5, 0.5);
                element.RenderTransform = new RotateTransform((double)e.NewValue);
            }
        }

添加完成後,咱們在編輯器中,看到以下效果:

若是咱們運行,則效果以下:

相比於前面挨個挨個的添加Rotate效果,程序是Clearn不少?這就是附加屬性帶來的便利。

完整的RotationManager.cs以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;//necessary

namespace CreatingAnAttachedProperty
{
    class RotationManager: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("Angle", typeof(double), typeof(RotationManager), new PropertyMetadata(0.0,OnAngleChanged));

        private static void OnAngleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var element = obj as UIElement;
            if (element != null)
            {
                element.RenderTransformOrigin = new Point(0.5, 0.5);
                element.RenderTransform = new RotateTransform((double)e.NewValue);
            }
        }        
    }
}
View Code

 

Update

WPF: Creating parameterized styles with attached properties

 

Wish it helps.

相關文章
相關標籤/搜索