wpf 依赖项属性

前端之家收集整理的这篇文章主要介绍了wpf 依赖项属性前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

UI软件中经常会用到大量的控件,而每一个控件都是一个对象,每一个类都会有大量的属性,如果没创建一个对象就将所有的属性都创建出来,无非会占用大量的内存,wpf使用依赖项属性来提升了性能

查看任何一个控件的定义,以button为例,都会发现类内包含大量的依赖性属性定义,注意到其中DependencyProperty都是static readonly的,而每一个依赖项属性都会有一个去掉“Property”的CLR属性和他对应,而我们在xaml中访问的都是CLR属性

public static readonly DependencyProperty IsCancelProperty;
public static readonly DependencyProperty IsDefaultedProperty;
public static readonly DependencyProperty IsDefaultProperty;

public bool IsCancel { get; set; }
public bool IsDefault { get; set; }
public bool IsDefaulted { get; }


如果我们自定义一个依赖项属性方法是这样的

public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name",typeof(string),typeof(ProvienceInfo));

//private string name;
public string Name
{
set
{
//if (name != value)
{
SetValue(NameProperty,value);
}
}
get
{
return GetValue(NameProperty).ToString();
}
}

注意到使用DependencyProperty的静态方法register将该属性注册到DependencyProperty@H_502_39@上,DependencyProperty类的内部包含一个hashtable,所有的依赖项属性都存在这个哈希表中,哈希表的key为由DependencyProperty的name和ownertype组成的类,且使用name+ownertype作为的哈希值,这样就可以确保每个key是不重复的

private class FromNameKey{

//Fields private int _hashCode;

privatestring _name;

private Type_ownerType;

// Methods

publicFromNameKey(string name,Type ownerType)

{

this._name = name;

this._ownerType = ownerType;

this._hashCode =

this._name.GetHashCode() ^

this._ownerType.GetHashCode();

} //省略代码...............}

依赖项属性到底是怎么样节约内存的呢,由于我们创建控件对象时只会设置很少一部分属性,大部分属性都是使用默认值,默认值也就是所有的对象都是一样的,那就可以使用静态属性来表示了,上面提到的存储依赖项属性的hashtable就发挥作用了,clr将所有没有设置的属性存放在这个hashtable中,对于设置了值的属性,则会为这个对象创建一个数组,类型为EffectiveValueEntry,包含了一个属性的index,dependencyproperty提供了一个方法getglobalindex来获取属性在hashtable中的位置,value当然就可以在此取出。

internalstructEffectiveValueEntry

{

internalintPropertyIndex{get;set;}

internalobjectValue{get;set;}

}

这也是为什么依赖项属性注册为static readonly的却可以修改的原因。

依赖项属性还给我们提供了什么其他好处

数据绑定:当我们绑定到数据源时,如果数据源的变更要想通知到UI,就需要实现inotifypropertychange接口,但如果将绑定源声明为依赖项属性,则可以直接通知更新UI。
资源的引用:还没搞懂,需要查

本地值:动画改变的属性只是改变临时变量,并未改变属性

附加属性和附加事件:

附加属性是全局的依赖属性,依赖属性属于某个类,而附加属性可以用在其他对象上,最简单,如Grid.row可以直接在Grid内的控件上设置

如果需要手动添加附加属性方法和依赖属性差不多,使用DependencyProperty.RegisterAttached方法

附加事件我的理解和附加属性差不多,也是全局的事件,可以附加到容器下的所有相应的控件上,如

<Grid ButtonBase.Click="bt_Click" Selector.SelectionChanged="Grid_SelectionChanged"@H_502_39@>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Name="ProvienceComboBox" Height="30" ItemsSource="{Binding Path=Proviences}" SelectionChanged="ComboBox_SelectionChanged"
SelectedValuePath="Id" DisplayMemberPath="Name" SelectedIndex="0">
</ComboBox>
<ComboBox Grid.Row="1" Name="CityComboBox" Height="30" SelectedIndex="0" SelectedValuePath="Id" DisplayMemberPath="Name">
</ComboBox>
<Button Grid.Row="2" Name="bt" Height="30" Width="60" Content="update" />
<Button Grid.Row="3" Height="30" Width="60" Content="update" />

</Grid>

这些事件会沿着视觉树向子元素寻找,直到找到相应的控件,并通知其相应事件,但后台出来事件的sender为grid,可以通过e.originalsource来查看事件的触发控件。

猜你在找的设计模式相关文章