WPF整理-为控件添加自定义附加属性

Posted lonelyxmas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF整理-为控件添加自定义附加属性相关的知识,希望对你有一定的参考价值。

原文:WPF整理-为控件添加自定义附加属性

附加属性,大家都不陌生,最常见的是Canvas.Left/Canvas.Top,类似的也有Grid.Row/Grid.Column等附加属性。举个最常见的例子

<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风马牛不相及,两者之间没有任何关系。

这就是关于附加属性DebugLZQ认为需要说明的地方。

为控件添加一个自定义的附加属性

1.我们有这样的一个XAML

    <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>

假如,我们需要实现控件绕中心旋转一定的角度。通常我们需要写类似的Rotate

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

当然这样OK,程序运行没有问题。
但,缺点是需要写较多的代码;当我们需要为页面其他所有元素实现旋转时,又需要写大量类似的代码。

我们可以通过附加属性来简化代码。如何做呢?

2.为工程添加一个名为RotationManager的类,我们在这个类中添加一个附加属性,让其他都能使用这个附加属性。

我们在类中键入"propa"

技术分享图片

和依赖属性类似,连按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);
            }
        }        
    }
}
技术分享图片

 

Update

WPF: Creating parameterized styles with attached properties







以上是关于WPF整理-为控件添加自定义附加属性的主要内容,如果未能解决你的问题,请参考以下文章

2016-11-11坚持学习Day24WPF 自定义控件 附加属性 自定义事件

WPF 使用附加属性增加控件属性

请教关于WPF上自定义控件添加事件的问题

wpf下拉多选自定义控件添加change事件

WPF利用依赖属性和命令编写自定义控件

WPF 自定义控件中,集合属性怎么做?