在WPF中,成为“依赖属性”意味着什么呢?
我读过微软的Dependency Properties Overview,但它并没有真正吸引我。部分文章说:
样式和模板是使用依赖项属性的两个主要激励方案。样式对于设置定义应用程序用户界面(UI)的属性特别有用。样式通常定义为XAML中的资源。样式与属性系统交互,因为它们通常包含特定属性的“setter”,以及根据另一个属性的实时值更改属性值的“触发器”。
然后示例代码是这样的:
<Style x:Key="GreenButtonStyle">
<Setter Property="Control.Background" Value="Green"/>
</Style>
....
<Button Style="{StaticResource GreenButtonStyle}">I am green!</Button>
但我没有得到有关此事的特别之处。是否只是暗示,当我将按钮上的Style
设置为给定样式时,我实际上是在隐式设置Background
?这是它的关键吗?
答案 0 :(得分:27)
答案 1 :(得分:9)
了解依赖属性试图解决的问题可能会有所帮助。
如果我们将Binding,Animation和Change Event模型放在一边,就像在其他答案中讨论过一样,那么好处就是内存使用,因此可以在窗口中托管数千个WPF对象。
如果一个窗口包含1000个Label
个对象,每个Label
对象具有通常的Foreground
,Background
,FontFamily
,FontSize
,{ {1}}等等,传统上这会消耗内存,因为每个属性都有一个私有支持字段来存储值。
大多数应用程序只会更改少数属性,其中大部分将保留其默认值。基本上非常浪费和冗余的信息(每个对象只在内存中保存相同的默认值)
这是依赖属性不同的地方。
FontWeight
没有私人支持字段。注册依赖项属性时,可以指定默认值。因此,在大多数情况下,// Lets register the Dependency Property with a default value of 20.5
public static readonly DependencyProperty ColumnWidthProperty =
DependencyProperty.Register("ColumnWidth", typeof(double), typeof(MyWPFControl), new UIPropertyMetadata(20.5, ColWitdhPropChanged));
public double ColumnWidth
{
get { return (double)GetValue(ColumnWidthProperty); }
set { SetValue(ColumnWidthProperty, value); }
}
返回的值是默认值,该值仅存储一次,以覆盖应用程序所有窗口中GetValue
对象的所有实例。
使用Label
设置依赖项属性时,它会将非默认值存储在由对象实例标识的集合中,以便在所有后续SetValue
调用中返回。
因此,此存储方法仅消耗已从默认值更改的WPF对象的属性的内存。即仅与默认值的差异。
答案 2 :(得分:8)
在WPF中,成为“依赖属性”意味着什么呢?
为了成为依赖属性,该属性实际上必须在类上静态地定义为DependencyProperty。依赖属性系统与标准CLR属性非常不同。
但是,依赖性属性的处理方式却截然不同。类型定义依赖项属性静态,并提供默认值。在需要之前,运行时实际上不会为实例生成值。这提供了一个好处 - 在请求类型之前该属性不存在,因此您可以拥有大量属性而无需开销。
这就是使样式工作属性的原因,但同样重要的是允许附加属性,通过可视树的属性“继承”以及WPF所依赖的许多其他东西。
例如,获取DataContext
依赖项属性。通常,您为Window或UserControl设置DataContext
依赖项属性。默认情况下,该窗口中的所有控件都会自动“继承”其父级DataContext
proeprty,这允许您为控件指定数据绑定。使用标准CLR属性,您需要为窗口中的每个控件定义DataContext,以便使绑定正常工作。
答案 3 :(得分:0)
简单/基本差异 - 更改通知:对更改依赖属性的更改在UI中在更改时反映/刷新,而CLR属性则不会。
<Window x:Class="SampleWPF.MainWindow"
x:Name="MainForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SampleWPF"
Title="About WPF Unleashed" SizeToContent="WidthAndHeight"
Background="OrangeRed"
>
<StackPanel DataContext="{Binding ElementName=MainForm}">
<!-- Bind to Dependency Property -->
<Label Name="txtCount1" FontWeight="Bold" FontSize="20" Content="{Binding ElementName=MainForm, Path=Count1, Mode=OneWay}" />
<!-- Bind to CLR Property -->
<Label Name="txtCount2" Content="{Binding ElementName=MainForm, Path=Count2, Mode=OneWay}"></Label>
<!-- Bind to Dependency Property (Using DataContext declared in StackPanel) -->
<Label Name="txtCount3" FontWeight="Bold" FontSize="20" Content="{Binding Count1}" />
<!-- Child Control binding to Dependency Property (Which propagates down element tree) -->
<local:UserControl1 />
<!-- Child Control binding to CLR Property (Won't work as CLR properties don't propagate down element tree) -->
<local:UserControl2 />
<TextBox Text="{Binding ElementName=txtCount1, Path=Content}" ></TextBox>
<TextBox Text="{Binding ElementName=txtCount2, Path=Content}" ></TextBox>
<Button Name="btnButton1" Click="btnButton1_Click_1">Increment1</Button>
<Button Name="btnButton2" Click="btnButton1_Click_2">Increment2</Button>
</StackPanel>
</Window>
<UserControl x:Class="SampleWPF.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
<Label Content="{Binding Count1}" ></Label>
<!--
<Label Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Count1}"></Label>
-->
</StackPanel>
</UserControl>
<UserControl x:Class="SampleWPF.UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
<Label Content="{Binding Count2}" ></Label>
<!--
<Label Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Count2}"></Label>
-->
</StackPanel>
</UserControl>
这里的代码(声明CLR和Dependency属性):
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.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SampleWPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public static readonly DependencyProperty Count1Property;
private int _Count2 = 2;
public int Count2
{
get { return _Count2; }
set { _Count2 = value; }
}
public MainWindow()
{
return;
}
static MainWindow()
{
// Register the property
MainWindow.Count1Property =
DependencyProperty.Register("Count1",
typeof(int), typeof(MainWindow),
new FrameworkPropertyMetadata(1,
new PropertyChangedCallback(OnCount1Changed)));
}
// A .NET property wrapper (optional)
public int Count1
{
get { return (int)GetValue(MainWindow.Count1Property); }
set { SetValue(MainWindow.Count1Property, value); }
}
// A property changed callback (optional)
private static void OnCount1Changed(
DependencyObject o, DependencyPropertyChangedEventArgs e) {
}
private void btnButton1_Click_1(object sender, RoutedEventArgs e)
{
Count1++;
}
private void btnButton1_Click_2(object sender, RoutedEventArgs e)
{
Count2++;
}
}
}
依赖属性提供的另一个功能是值继承 - 顶级元素中设置的值沿元素树向下传播 - 在以下从http://en.csharp-online.net获取的示例中,在“Window”标记上声明的FontSize和FontStyle应用于所有子级下面的元素:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="About WPF Unleashed" SizeToContent="WidthAndHeight"
FontSize="30" FontStyle="Italic"
Background="OrangeRed">
<StackPanel>
<Label FontWeight="Bold" FontSize="20" Foreground="White">
WPF Unleashed (Version 3.0)
</Label>
<Label>© 2006 SAMS Publishing</Label>
<Label>Installed Chapters:</Label>
<ListBox>
<ListBoxItem>Chapter 1</ListBoxItem>
<ListBoxItem>Chapter 2</ListBoxItem>
</ListBox>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button MinWidth="75" Margin="10">Help</Button>
<Button MinWidth="75" Margin="10">OK</Button>
</StackPanel>
<StatusBar>You have successfully registered this product.</StatusBar>
</StackPanel>
</Window>
<强>参考文献:强> http://www.codeproject.com/Articles/29054/WPF-Data-Binding-Part-1 http://en.csharp-online.net/WPF_Concepts%E2%80%94Property_Value_Inheritance