tee*_*nup 9 wpf dependency-properties
我在以下链接中读到了这个: -
http://www.informit.com/articles/article.aspx?p=688529&seqNum=2
但是,因为GetValue和SetValue在内部使用高效的稀疏存储系统,并且因为IsDefaultProperty是静态字段(而不是实例字段),所以依赖属性实现与典型的.NET属性相比可以节省每个实例的内存.如果WPF控件上的所有属性都是围绕实例字段的包装器(与大多数.NET属性一样),则由于每个实例附加的所有本地数据,它们将占用大量内存.
但最终它们会被存储在某个地方,它如何节省内存消耗?
Fre*_*lad 17
请参阅以下链接:http://www.bobpowell.net/dependencyproperty.aspx
对象声明为依赖属性的内容实际上只不过是一个标识符.这个静态"属性"实际上是一个将对象与特定存储标识符相关联的键.例如,图形对象具有可以显式设置或通过使用模板或样式设置的Background属性.
只要依赖属性使用其默认状态(这是非常常见的),它将不会占用任何额外的内存,因为将使用默认值.默认值不是每个实例存储的,它是根据Dependency Property存储的,它由元数据设置.
例如,请注意如何Brushes.Black设置为默认值
public static readonly DependencyProperty ForegroundProperty =
DependencyProperty.Register(
"Foreground",
typeof(Brush),
typeof(TextElement),
new FrameworkPropertyMetadata(Brushes.Black, ...));
Run Code Online (Sandbox Code Playgroud)
可以这样想:假设您TextBlocks在Xaml中有四个
<StackPanel>
<TextBlock .../>
<TextBlock .../>
<TextBlock .../>
<TextBlock Foreground="Green" .../>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
尽管您从未明确将其设置为黑色,但TextBlocks顶部的三个已Foreground设置为黑色.他们正在使用他们的默认值.因此,对于上述三个属性,您只需要一个字段(因为它是一个静态字段).ForegroundTextBlocks
对于第四个TextBlock,您已明确设置Foreground为绿色,因此该值作为Foreground此实例的本地值插入字典中,因此需要额外的内存(此外,它将最终位于下面列表中的第3位,覆盖Setters,Triggers等等).
另外,请参阅Josh Smith的以下文章,这是一个很好的解读:揭开依赖属性的神秘面纱
有一套明确定义的规则,WPF在内部使用这些规则来确定DP的实际价值.以下是解析DP值时使用的优先规则的简要概述(在此处详细了解):
- 财产制度强制
- 活动动画或具有保持行为的动画
- 本地价值
- TemplatedParent模板
- 风格触发器
- 模板触发器
- 风格二传手
- 主题风格
- 遗产
- 依赖项属性元数据的默认值
编辑:回答杜安的评论
如果将值显式设置为与默认值相同的值,它仍将存储为本地值.使用以下Xaml可以轻松验证这一点.
两者都TextBlocks将Foreground设置为黑色,但后者具有本地值集.由于样式设置器的优先级低于本地值,Style因此只能Foreground在第一个TextBlock而不是后一个设置.
<StackPanel>
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Green"/>
</Style>
</StackPanel.Resources>
<TextBlock Text="Displays in Green"/>
<TextBlock Foreground="Black" Text="Displays in Black"/>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
首先,假设您创建了一个包含十几个属性的类.创造100,000个.你现在有多少个对象引用?1200000.
现在实现一个名为的类DependencyObject:
public class DependencyObject
{
public DependencyObject()
{
LocalValues = new Dictionary<string, object>();
}
protected Dictionary<string, object> LocalValues { get; set; }
public DependencyObject Parent { get; set; }
protected object GetValue(string propertyName)
{
if (LocalValues.ContainsKey(propertyName))
{
return LocalValues[propertyName];
}
return Parent.GetValue(propertyName);
}
protected void SetValue(string propertyName, object value)
{
LocalValues[propertyName] = value;
}
}
Run Code Online (Sandbox Code Playgroud)
像这样构建一个派生类:
public class MyDependencyObject : DependencyObject
{
public SomeType Property1
{
get { return (SomeType)GetValue("Property1"); }
set { SetValue("Property1", value]; }
}
// create 11 more properties like this
}
Run Code Online (Sandbox Code Playgroud)
现在创建100,000个实例MyDependencyObject并设置它们Parent.使用了多少个对象引用(不包括父对象)?300,000.
这就是属性值继承在依赖对象中的工作方式.