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

简介: 原文:WPF QuickStart系列之附加属性(Attached Property)这一篇博客是关于如何使用附加属性和创建自定义附加属性的。 1. 附加属性使用, WPF中对附加属性使用最多的莫过于对控件布局时设置控件的位置,例如在Canvas中有一个Rectangle, Ellipse, ...
原文: 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属性不是依赖属性,此时使用自定义附加属性解决了这个问题。示例代码下载

目录
相关文章
|
6月前
|
C#
2000条你应知的WPF小姿势 基础篇<57-62 依赖属性进阶>
2000条你应知的WPF小姿势 基础篇<57-62 依赖属性进阶>
20 0
|
6月前
|
存储 开发框架 .NET
2000条你应知的WPF小姿势 基础篇<51-56 依赖属性>
2000条你应知的WPF小姿势 基础篇<51-56 依赖属性>
21 0
|
9月前
|
C#
WPF属性---重复样式和触发器
WPF属性---重复样式和触发器
70 0
WPF项目中不支持 ResizingPanel,未在类型“ResizingPanel”中找到可附加的属性“ResizeWidth”
WPF项目中不支持 ResizingPanel,未在类型“ResizingPanel”中找到可附加的属性“ResizeWidth”
|
C#
WPF整理-为控件添加自定义附加属性
原文:WPF整理-为控件添加自定义附加属性 附加属性,大家都不陌生,最常见的是Canvas.Left/Canvas.Top,类似的也有Grid.Row/Grid.Column等附加属性。举个最常见的例子 需要说明的是并不是所有的附加属性都是元素放进去后才会有附加效果,上面的例子只是刚好是这种错觉的巧合情况,Grid.Row也属于这种巧合。
2041 0
|
C#
WPF的IsSynchronizedWithCurrentItem属性
原文:WPF的IsSynchronizedWithCurrentItem属性 如果两个控件都绑定到同一个源(ObservableCollection)集合视图时,该对象会自动绑定到该视图的 CurrentItem。
953 0
|
C# 数据安全/隐私保护
WPF 使用附加属性增加控件属性
原文:WPF 使用附加属性增加控件属性 使用附加属性增加控件属性,使得这个附加属性在使用的时候没有局限性,可以在任何的控件中使用它来增加所需要的属性,使得控件的属性使用起来非常灵活   一、自定义附加属性 1 2 3 4 5 6 7 8 9 10 11 ...
851 0
|
.NET C#
深入浅出WPF——附加事件(Attached Event)
原文:深入浅出WPF——附加事件(Attached Event)   3.3 事件也附加——深入浅出附加事件                 WPF事件系统中还有一种事件被称为附加事件(Attached Event),简言之,它就是路由事件。
1176 0
|
C#
WPF中一个控件绑定另一个控件的属性
原文:WPF中一个控件绑定另一个控件的属性 如同一个Grid中的一个按钮根据另一个按钮的显示与否作出不同的响应: 绑定的时候通过ElementName来指定控件               ...
1801 0
|
C#
WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性
原文:WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性 如果你要自定义一个图片按钮控件,那么如何在主窗体绑定这个控件上图片的Source呢? 我向大家介绍一个用 依赖属性(DependencyProperty) 实现的方法。
2437 0