在WPF(Windows Presentation Foundation)中,依赖属性和附加属性是两种非常有用的特性,它们扩展了传统属性的功能,提供了更强大的数据绑定、样式和模板定制能力。
一:依赖属性(Dependency Properties)
依赖属性是WPF中的一种特殊类型的属性,它们基于DependencyProperty类。与传统的CLR(公共语言运行时)属性不同,依赖属性没有存储值的后备字段;相反,它们的值存储在DependencyObject的PropertyStore中。这使得依赖属性能够支持许多高级功能,如数据绑定、样式、动画和继承。
-
声明依赖属性
在WPF中,你通常使用DependencyProperty.Register或DependencyProperty.RegisterReadOnly方法来注册一个依赖属性。例如:
public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register(
"MyProperty", typeof(string), typeof(MyClass), new PropertyMetadata("DefaultValue"));
public string MyProperty
{
get { return (string)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
在这个例子中,MyProperty是一个依赖属性,它有一个类型为string的值,并在MyClass类中注册。
-
实战使用:
我们给自定义button添加一个依赖属性,并在使用时通过ControlTemplate进行重组时进行依赖属性绑定
定义部分:
public class JSCButton : Button
{
// 注册依赖属性
public static readonly DependencyProperty ImageSourceExProperty =
DependencyProperty.Register("ImageSourceEx", typeof(ImageSource), typeof(JSCButton), new PropertyMetadata(null));
// CLR包装器属性
public ImageSource ImageSourceEx
{
get { return (ImageSource)GetValue(ImageSourceExProperty); }
set { SetValue(ImageSourceExProperty, value); }
}
}
ButtonStyle1部分:
<Style x:Key="ButtonStyle1" TargetType="{x:Type local:JSCButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:JSCButton}">
<Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="3*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Border Grid.Row="1" Background="Red" Width="86" Height="87">
<Image Width="50" Height="50" Source="{TemplateBinding ImageSourceEx}"/>
</Border>
<TextBlock Grid.Row="2" Text="{TemplateBinding Content}" FontSize="18" TextAlignment="Center"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
使用部分:
<local:JSCButton ImageSourceEx="/Resources/CompileResources/Images/next.png" Grid.Column="0" Content="音量+" Grid.Row="0" Style="{StaticResource ButtonStyle1}"/>
<local:JSCButton ImageSourceEx="/Resources/CompileResources/Images/next.png" Grid.Column="1" Content="当前分贝" Grid.Row="0" Style="{StaticResource ButtonStyle1}"/>
<local:JSCButton ImageSourceEx="/Resources/CompileResources/Images/next.png" Grid.Column="2" Content="音量-" Grid.Row="0" Style="{StaticResource ButtonStyle1}"/>
呈现效果:
这样我们既使用控件模板自定义了button,使其增加了image图片展示部分,又可以给不同的button使用不同的图片赋值展示。
二:附加属性(Attached Properties)
附加属性允许你将属性附加到任何对象上,而不仅仅是该类本身的实例。这允许开发者定义可以在任何元素上使用的属性,而不需要继承自该元素的类。附加属性通常用于控件模板、样式或布局中,以提供额外的功能或信息。
-
声明附加属性
附加属性也是基于DependencyProperty的,但是它们通过静态Get和Set方法而不是普通的CLR属性访问器来访问。例如:
public static readonly DependencyProperty MyAttachedPropertyProperty = DependencyProperty.RegisterAttached(
"MyAttachedProperty", typeof(string), typeof(MyAttachedProperties), new PropertyMetadata(default(string)));
public static void SetMyAttachedProperty(DependencyObject element, string value)
{
element.SetValue(MyAttachedPropertyProperty, value);
}
public static string GetMyAttachedProperty(DependencyObject element)
{
return (string)element.GetValue(MyAttachedPropertyProperty);
}
在这个例子中,MyAttachedProperty是一个附加属性,它可以通过SetMyAttachedProperty和GetMyAttachedProperty方法附加到任何DependencyObject上。
-
实战使用:
我们添加一个静态类,给它添加一个附加属性ImageSource,并在使用Button时通过ControlTemplate进行重组时进行附加属性绑定。
定义部分:
public static class JSCProperties
{
public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.RegisterAttached("ImageSource", typeof(ImageSource), typeof(JSCProperties), new PropertyMetadata(null));
public static void SetImageSource(DependencyObject element, ImageSource value)
{
element.SetValue(ImageSourceProperty, value);
}
public static ImageSource GetImageSource(DependencyObject element)
{
return (ImageSource)element.GetValue(ImageSourceProperty);
}
}
buttonStyle部分
<Window.Resources>
<Style x:Key="buttonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border>
<StackPanel>
<Image Width="50" Stretch="Uniform" Height="50" Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:JSCProperties.ImageSource)}"/>
<TextBlock Text="{TemplateBinding Content}" FontSize="18" TextAlignment="Center"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
使用部分
<Grid>
<Button local:JSCProperties.ImageSource="/Images/next.png" Content="按钮" Width="100" Height="80" Style="{StaticResource buttonStyle}"/>
</Grid>
呈现效果
总结
依赖属性:是WPF特有的,用于支持数据绑定、样式、动画等高级功能。它们通常用于控件类,但也可以用于任何继承自DependencyObject的类。
附加属性:允许你将属性附加到任何DependencyObject上,而不仅仅是该属性的定义类。这提供了一种灵活的方式来在不修改类继承层次结构的情况下扩展类的功能。
这两种属性在WPF开发中非常有用,它们极大地增强了WPF应用程序的灵活性和可定制性。
网友评论