wpf附加屬性詳解

為什麼使用附加屬性

附加屬性的一個用途是允許不同的子元素為父元素中定義的屬性指定唯一的值。 此方案的一個具體應用是,讓子元素通知父元素它們在用戶介面 (UI) 中的呈現方式。 一個示例是 DockPanel.Dock 屬性。 該 DockPanel.Dock 屬性是作為附加屬性創建的,因為它設計為在中包含的元素上設置,而不是在自身中包含的元素上設置 DockPanel DockPanel 。 DockPanel類定義 DependencyProperty 名為的靜態欄位 DockProperty ,然後提供 GetDock 和 SetDock 方法作為附加屬性的公共訪問器。

一、附加屬性的特點

1、特殊的依賴屬性
2、用於非定義該屬性的類 例如Grid面板的RowDefinition、ColumnDefinition、Canvas面板的Left、Right,DockPanel面板的Dock都是附加屬性。

二、附加屬性的定義

1、聲明數據屬性變數。 public static 的DependencyProperty類型的變數。
2、在屬性系統中進行註冊,使用DependencyProperty.RegisterAttached()方法來註冊,方法參數和註冊依賴屬性時Register()方法的參數一致。
3、調用靜態方法設置和獲取屬性值。通過調用DependencyObject的SetValue()和GetValue()方法來設置和獲取屬性的值。兩個方法應該命名為SetPropertyName()方法和GetPropertyName()方法。

 

三、示例(給頁面上的Grid表格控制項做特殊邊框樣式)

創建幫助類定義並註冊附加屬性:

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media;

namespace Opacs.Client.Utilities

{

    public static class GridHelper

    {

        public static bool GetShowBorder(DependencyObject obj)

        {

            return (bool)obj.GetValue(ShowBorderProperty);

        }

 

        public static void SetShowBorder(DependencyObject obj, bool value)

        {

            obj.SetValue(ShowBorderProperty, value);

        }

 

        public static readonly DependencyProperty ShowBorderProperty =

            DependencyProperty.RegisterAttached(“ShowBorder”, typeof(bool), typeof(GridHelper), new PropertyMetadata(OnShowBorderChanged));

 

        private static void OnShowBorderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            var grid = d as Grid;

            if ((bool)e.OldValue)

            {

                grid.Initialized -= (s, arg) => { };

            }

            if ((bool)e.NewValue)

            {

                grid.Initialized += (s, arg) =>

                {

                    var controls = grid.Children;

                    var count = controls.Count;

                    for (var i = 0; i < count; i++)

                    {

                        var item = controls[i] as FrameworkElement;

                        #region 單元格邊框Thickness詳細設計                    

                        var rowCount = grid.RowDefinitions.Count;

                        var columnCount = grid.ColumnDefinitions.Count;

                        var row = Grid.GetRow(item);

                        var column = Grid.GetColumn(item);

                        var rowspan = Grid.GetRowSpan(item);

                        var columnspan = Grid.GetColumnSpan(item);

                        var thicknessValue = 1;

                        var thickness = new Thickness(thicknessValue);

                        var thicknessColor = Colors.DarkGray;

                        var background = new SolidColorBrush(Colors.White);

                        if (row == 0)

                        {

                            background = new SolidColorBrush(Colors.LightGray);

                        }

                        if (row > 0 && row <= rowCount – 1)

                        {

                            thickness.Top = 0;

                        }

                        if (column > 0 && column <= columnCount – 1)

                        {

                            thickness.Left = 0;

                        }             

                        item.BorderThicknessRemove(ref thickness);

                        #endregion

 

                        var border = new Border()

                        {

                            BorderBrush = new SolidColorBrush(thicknessColor),

                            BorderThickness = thickness,

                            Background = background

                        };

 

                        Grid.SetRow(border, row);

                        Grid.SetColumn(border, column);

                        Grid.SetRowSpan(border, rowspan);

                        Grid.SetColumnSpan(border, columnspan);

 

                        grid.Children.RemoveAt(i);

                        border.Child = item;

                        grid.Children.Insert(i, border);

                    }

                };

            }

        }

 

        public static void BorderThicknessRemove(this FrameworkElement item, ref Thickness thickness)

        {

            if (item.Tag != null)

            {

                if (item.Tag.Equals(“LeftWideBorder”))

                {

                    thickness.Left = 0;

                }

                if (item.Tag.Equals(“RightWideBorder”))

                {

                    thickness.Right = 0;

                }

            }

        }

 

    }

}

 

在xaml頁面上使用附加屬性:

<dxwui:NavigationPage

    x:Class=”Opacs.Client.Views.UserCheck.OptometryView”

    xmlns=”//schemas.microsoft.com/winfx/2006/xaml/presentation”

    xmlns:x=”//schemas.microsoft.com/winfx/2006/xaml”

    xmlns:utilities=”clr-namespace:Opacs.Client.Utilities”>

<Grid

  HorizontalAlignment=”Stretch”

  VerticalAlignment=”Stretch”

  utilities:GridHelper.ShowBorder=”True”>    //功能是給grid表格添加自定義的邊框

  <Grid.ColumnDefinitions>

    <ColumnDefinition Width=”*” />

  </Grid.ColumnDefinitions>

  <Grid.RowDefinitions>

    <RowDefinition Height=”Auto” />

  </Grid.RowDefinitions>

<TextBlock

  Grid.Row=”0″

  Grid.Column=”0″

  VerticalAlignment=”Center”

  TextAlignment=”Center”

  TextWrapping=”Wrap” />

</Grid>

<dxwui:NavigationPage>

 

四、附加屬性的另外一種用法:

定義附加屬性類

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Input;

using System.Windows.Media;

namespace Demo3.Control

{

    public class ControlAttachProperty

    {

        #region 圓角

        public static CornerRadius GetCornerRadius(DependencyObject obj)

        {

            return (CornerRadius)obj.GetValue(CornerRadiusProperty);

        }

 

        public static void SetCornerRadius(DependencyObject obj, CornerRadius value)

        {

            obj.SetValue(CornerRadiusProperty, value);

        }

 

        public static readonly DependencyProperty CornerRadiusProperty =

            DependencyProperty.RegisterAttached(“CornerRadius”, typeof(CornerRadius), typeof(ControlAttachProperty), new PropertyMetadata(null));         

        #endregion       

    }

}

 

在xaml頁面使用它:

給自定義的附加屬性賦值

<Window x:Class=”Demo3.MainWindow”

        xmlns=”//schemas.microsoft.com/winfx/2006/xaml/presentation”

        xmlns:x=”//schemas.microsoft.com/winfx/2006/xaml”

        xmlns:c=”clr-namespace:Demo3.Control”

        Background=”Black”

        Title=”MainWindow”

        WindowStartupLocation=”CenterScreen”

        Height=”350″

        Width=”525″>

    <StackPanel>

        <TextBox x:Name=”UserName”

                 Width=”230″

                 Height=”38″

                 Margin=”0,20,0,0″

                 FontSize=”18″

                 VerticalContentAlignment=”Center”

                 c:ControlAttachProperty.CornerRadius=”5″ />     //給自定義的附加屬性賦值

                 Style=”{StaticResource DefaultTextBox}”

    </StackPanel>      

</Window>

 

在style文件中進行使用

<ResourceDictionary xmlns=”//schemas.microsoft.com/winfx/2006/xaml/presentation”

                    xmlns:c=”clr-namespace:Demo3.Control”

                    xmlns:x=”//schemas.microsoft.com/winfx/2006/xaml”>

     

    <ResourceDictionary.MergedDictionaries>

        <ResourceDictionary Source=”/Demo3;component/Resources/Style/DeleteButton.xaml” />

    </ResourceDictionary.MergedDictionaries>

     

    <!–TextBox默認樣式–>

    <Style x:Key=”DefaultTextBox” TargetType=”{x:Type TextBox}”>

        <Setter Property=”ContextMenu” Value=”{DynamicResource TextBoxContextMenu}” />

        <Setter Property=”VerticalContentAlignment” Value=”Center” />

        <Setter Property=”SnapsToDevicePixels” Value=”True” />

        <Setter Property=”Template”>

            <Setter.Value>

                <ControlTemplate TargetType=”{x:Type TextBox}”>

                    <Border x:Name=”Bg”

                            SnapsToDevicePixels=”{TemplateBinding SnapsToDevicePixels}”

                            CornerRadius=”{TemplateBinding c:ControlAttachProperty.CornerRadius}”    //這裡的Border控制項的CornerRadius屬性的值=(TemplateBinding)父級的c:ControlAttachProperty.CornerRadius附加屬性的值=5

                            Background=”White”

                            BorderBrush=”Transparent”

                            BorderThickness=”0″>                       

                    </Border>                                       

                </ControlTemplate>

            </Setter.Value>

        </Setter>

    </Style>

     

</ResourceDictionary>

Tags: