好的,我相信你已经决定了要使用DependencyProperty而不是传统的CLR属性,正如上一篇Post所说,很多地方都需要使用到DependencyProperty,作为例子,我决定定义一个MyBorderEx,在WPF常用的"Border"控件中创建一个名为Transparency的属性,来指示它的透明度,这个属性值在0-255间变化,255表示全透明,0表示完全不透明。
我们首先定义这个DependencyProperty:
DependencyProperty.Register(
"Transparency",
typeof(Double),
typeof(MyBorderEx)
);
public Double Transparency
{
get { return (Double)GetValue(TransparencyDependency); }
set { SetValue(TransparencyDependency, value); }
}
我们只是定义了这个属性,不过这个属性更改时还不会自动的去更新MyBorderEx的透明度,其实WPF中包含有一个默认的名为Opacity的属性来完成这个工作,我们就借用他来实现这个功能。也许你会想这么做。
{
get { return (Double)GetValue(TransparencyDependency); }
set
{
SetValue(TransparencyDependency, value);
Opacity = 1 - ((double)value / 255);
}
}
{
public MyBorderEx()
{
//初始化时默认给定一个背景色
Background = Brushes.Blue;
}
public readonly static DependencyProperty TransparencyDependency =
DependencyProperty.Register(
"Transparency",
typeof(Double),
typeof(MyBorderEx),
new PropertyMetadata(new PropertyChangedCallback(transparencyPropertyChangedCallback))
);
static void transparencyPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MyBorderEx border = (sender as MyBorderEx);
if (border != null)
{
border.Opacity =1 - Convert.ToDouble(e.NewValue) / 255;
}
}
public Double Transparency
{
get { return (Double)GetValue(TransparencyDependency); }
set { SetValue(TransparencyDependency, value); }
}
}
主窗体中的XAML调用代码:
<Slider Grid.Row="1" HorizontalAlignment="Left" Name="slider1" Width="130" Value="50" Minimum="0" Maximum="255" />
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard x:Name="storyboardFadeIn" >
<DoubleAnimation From="255" To="0" Duration="00:00:03" Storyboard.TargetName="bord" Storyboard.TargetProperty="Transparency"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
<Button Name="btnFadeOut" Margin="0,0,28,7" HorizontalAlignment="Right" Grid.Row="1" Width="53" Content="FadeOut">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard x:Name="storyboardFadeOut" >
<DoubleAnimation From="0" To="255" Duration="00:00:03" Storyboard.TargetName="bord" Storyboard.TargetProperty="Transparency"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
上一篇Post提到的“反射”问题。不论在数据绑定还是动画中我们都只提供了一个属性名字符串,难道WPF真的需要使用反射读取属性数据?
如果我们在动画进行时同时通过Slider来改变DependencyProperty的值,会发生什么?此时Property中到底存储了来自哪里的值,是原始我们赋给的值?是数据绑定的值?还是当前动画的值?此时我们通过GetValue方法,会得到什么样的值呢?大家可以先用上面的程序测试一下。
小结
今天终于开始写代码了,我们使用DependencyProperty扩展了Border控件(当然这个扩展似乎没什么意义,仅仅作为例子),并且在我们自己的DependencyProperty上实现了简单的数据绑定和动画功能。在最后,我提出了一些问题,下一篇Post中我将以这些问题为线索,探讨一下DependencyProperty中值得存储方式。
附件里有一些主要的代码。
另外预告一下,前段时间我花了些时间研究了下DependencyProperty,本来我准备两三篇文章就“汇报”一下研究成果的,不过一写起来却发现内容真的挺多。今后的几篇Post大致会有以下内容:
关于DependencyProperty值的存储方式
关于AttachedProperty
使用PropertyMetadata的特性
关于PropertyMetadata特性实现机制
还是那句话,希望园子里研究WPF的同志们多多交流,希望和大家一起共同学习。
















