学习SL/WPF,Dependency Properties(依赖属性)是一个全新(陌生)但又无法回避的概念。 ­
http://www.wpftutorial.net/DependencyProperties.html ­
这里有一篇通俗易懂的相关文章,不过是E文的,E文不好的朋友,也可以参考下面的内容: ­
1.为什么会出现依赖属性? ­
­
先回想一下传统的属性(Property):通常我们读取或赋值一个属性时,实际上是在对属性背后的某个私 有成员进行读写。那么随着对象的属性越来越多,再加上从对象派生出去的子对象,子对象再生出“孙子”对象. .....最终的对象运行实例中会有大量的私有成员,而每私有成员都要分配内存,占用一定的资源。 ­
­
但反过来想想,通常我们在使用一个控件/对象时,往往只用到了某几个属性,大部分属性(有时候甚至达到90%以上)都是采用的默认值(或者也可以理 解为没有用到),这对于WPF/SL来说无疑是一种极大的性能损耗。 ­
­
所以在此背景之下,DP(Dependency Properties的简称)就出现了,我们再回想一下静态(static)方法或成员,静态成员/方法的调用不依赖于实例,它是class级别的,不管这个类有多少个实例,静态成员在内存中只占一份,这正 是我们所要的! ­
­
2.依赖属性的大致原理及好处 ­
­
所有具备依赖属性的对象,都是继承自DependencyObject,DependencyObject 中有一个"字典"存储区用来存放依赖属性,而且都是用static方式读取的,所以你现在应该想明白了:为 啥不能直接用txt.Left = xxx来直接赋值,而必须用txt.SetValue(Canvas.Left,xxx)来处理,因为st atic成员是实例无法调用的。 ­
­
DP的优点: ­
(1)有效降低内存消耗。 ­
(2)直接继承上级的属性值(这里也解释了为什么上级控件对下级控件自动布局,因为下级控件自动继承了上级 控件的相关属性值) ­
(3)自动实现了“变化通知”(dp有内置的Change Notification回调接口) ­
­
3.依赖属性值的读取策略 ­
­
­
这张图描述了GetValue与SetValue的内部读取策略. ­
­
4.依赖属性的使用示例: ­
­
下面我们演示如何给一个用户自定义控件添加Message依赖属性 ­
­
(1)先建一个Silverlight User Control,取名为MyControl ­
Java代码 ­
<UserControl x:Class="DPStudy.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
> <Border CornerRadius="5" BorderThickness="3" BorderBrush="#FFEF410D" Width="300" Height="40" Margin="5" > <TextBlock x:Name="txt" Text="" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border> </UserControl> <UserControl x:Class="DPStudy.MyControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Border CornerRadius="5" BorderThickness="3" BorderBrush="#FFEF410D" Width="300" Height="40" Margin="5" > <TextBlock x:Name="txt" Text="" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock> </Border></UserControl>­
­
CS部分:(技巧:vs2008中,
shape up shoes,只要键入propdp,
skechers tone ups,再连敲二次Tab键,vs就会自动添加一个依赖属性的代码模板) ­
Java代码 ­
using System.Windows; using System.Windows.Controls;
namespace DPStudy { public partial class MyControl : UserControl { public static readonly DependencyProperty MessageProperty = DependencyProperty.Register("Message",
shape ups skechers, typeof(string), typeof(MyControl), new PropertyMetadata("Message的默认值", new PropertyChangedCallback(OnMessagePropertyChanged)) );
public string Message { get { return (string)GetValue(MessageProperty); } set { SetValue(MessageProperty,
skechers women, value); } }
/// <summary>
/// Message变化时的通知处理
/// </summary>
/// <param name="d"></param>
/// <param name="e"></param>
private static void OnMessagePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { MyControl ctl = d as MyControl; ctl.txt.Text = d.GetValue(MyControl.MessageProperty).ToString(); }
public MyControl() { InitializeComponent();
this.Loaded += new RoutedEventHandler(MyControl_Loaded); }
void MyControl_Loaded(object sender, RoutedEventArgs e) { this.txt.Text = Message;//初始加载时,显示Message的初始值
} } } using System.Windows;using System.Windows.Controls;namespace DPStudy{ public partial class MyControl : UserControl { public static readonly DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(string), typeof(MyControl), new PropertyMetadata("Message的默认值", new PropertyChangedCallback(OnMessagePropertyChanged)) ); public string Message { get { return (string)GetValue(MessageProperty); } set { SetValue(MessageProperty, value); } } /// <summary> /// Message变化时的通知处理 /// </summary> /// <param name="d"></param> /// <param name="e"></param> private static void OnMessagePropertyChanged(DependencyObject d,
skechers shape ups, DependencyPropertyChangedEventArgs e) { MyControl ctl = d as MyControl; ctl.txt.Text = d.GetValue(MyControl.MessageProperty).ToString(); } public MyControl() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MyControl_Loaded); } void MyControl_Loaded(object sender, RoutedEventArgs e) { this.txt.Text = Message;//初始加载时,显示Message的初始值 } }}­
­
这里我们定义了一个Message的string类型依赖属性,
skechers shoes,和普通属性的区别是:必须使用DependencyProperty.Register来注册该属性,而 且“属性命名”要以Property为后缀;另外在读取时,必须调用SetValue/GetValue静态方法来读取其值,最后我们还可以添加一个"属性值变化时的"回调处理。 ­
­
(2)将MyControl放到MainPage.xaml中小试牛刀 ­
MainPage.Xaml内容如下: ­
Java代码 ­
<UserControl x:Class="DPStudy.MainPage"
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:l="clr-namespace:DPStudy"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"> <StackPanel x:Name="LayoutRoot"> <l:MyControl x:Name="myctl"></l:MyControl> <Button Click="Button_Click" Content="改变Message属性值" Width="130" ></Button> </StackPanel> </UserControl> <UserControl x:Class="DPStudy.MainPage" 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:l="clr-namespace:DPStudy" mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"> <StackPanel x:Name="LayoutRoot"> <l:MyControl x:Name="myctl"></l:MyControl> <Button Click="Button_Click" Content="改变Message属性值" Width="130" ></Button> </StackPanel></UserControl>­
­
MainPage.Xaml.cs内容如下: ­
Java代码 ­
using System.Windows; using System.Windows.Controls;
namespace DPStudy { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); }
private void Button_Click(object sender, RoutedEventArgs e) { myctl.SetValue(MyControl.MessageProperty, "新值"); } } } using System.Windows;using System.Windows.Controls;namespace DPStudy{ public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { myctl.SetValue(MyControl.MessageProperty, "新值"); } }}­
­
运行后,点击按钮将改变MyControl控件的Message属性值,同时MyControl中的文本控 件的文字也将变成"新值" ­