1 依赖属性

1.1 依赖属性最终值的选用

WPF属性系统对依赖属性操作的基本步骤如下:

第一,确定Base Value,对同一个属性的赋值可能发生在很多地方。还用Button的宽度来进行举例,可能在Style或者Trigger中对其进行赋值,也可能在xaml中进行赋值(等同与在代码中赋值),这个Base Value就要确定这些值中优先级最高的值,把它作为Base Value;

    <Window.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="30"/>
<Style.Triggers>
<Trigger Property="IsPressed" Value="False">
<Setter Property="Width" Value="3000"/>
</Trigger>
</Style.Triggers>
</Style>
<loc:WidthConvertr x:Key="WidthConverter"/>
</Window.Resources>
<Grid>
<Button Name="ButtonTest"
FontSize="13"
Background="Blue"
>ButtonSubSub</Button>
</Grid>

在代码中查看ValueSource截图为图1

看到BaseValueSource是StyleTrigger类型的,BaseValue在选取的规则中,都应当按照如下的优先级别进行选取,从上到下是依次增大的,可以看到StyleTrigger比Style要高,这和上边的xaml中示例中的相同,如果把Trigger去掉,那么BaseValueSource是Style了。如果xaml中什么都没有设定,在代码中也没有赋值,那么,BaseValueSource就会是Default类型;

    public enum BaseValueSource
    {
        Unknown = 0,
        Default = 1,
        Inherited = 2,
        DefaultStyle = 3,
        DefaultStyleTrigger = 4,
        Style = 5,
        TemplateTrigger = 6,
        StyleTrigger = 7,
        ImplicitStyleReference = 8,
        ParentTemplate = 9,
        ParentTemplateTrigger = 10,
        Local = 11,
    }

第二,获取绑定源中的值。这个步骤容易产生理解上的混乱,如果在第一步中,设置了LocalValue,即1.1中阐述的Binding或者在xaml中赋值,并且如果是Binding的话,就会经过第二步的计算,将其转化成一个实际的值;如果不是,就直接判断以下的情况;

第三,获取动画值。如果当前属性正在作动画,那么因动画而产生的值会优于前面获得的值,这个也就是WPF中常说的动画优先;

第四,对最终值进行强制值约定。利用在FrameworkPropertyMetadata中传入了CoerceValueCallback,进行数据的逻辑限制,例如边界限制,特殊值限制等。

第五,对最终值进行最后验证。利用在Register的时候传入了ValidateValueCallback;

参考http://www.cnblogs.com/Zhouyongh/archive/2009/10/20/1586278.html

1.2 LocalValue中的直接赋值和BindingExpress

依赖属性中的LocalValue,只能设置通过在xaml中赋值或者直接在代码中进行赋值或者通过Binding对赋值行绑定,但三种方式不能同时在依赖属性中进行存在,也就是说,这三种给依赖属性提供值的方式,在运行时,最后调用者覆盖之前为LocalValue的赋值,并且发生作用。

例如:先编写一个宽度的数据源

    public class WidhtHeightBindingedClass : INotifyPropertyChanged
{
private double _height;
public double Height
{
get
{
return _height;
}
set
{
_height = value;
Notify("Height");
}
}
private double _width;
public double Width
{
get
{
return _width;
} set
{
_width = value;
Notify("Width");
}
} public event PropertyChangedEventHandler PropertyChanged;
private void Notify(string proerptyName)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(proerptyName));
}
}
}

我们可以在xaml中,设置Button的宽度,

    <Grid>
<Button Name="ButtonTest"
FontSize="13"
Background="Blue"
Width="400"
>ButtonSubSub</Button>
</Grid>

但,在Loaded事件处理函数中,有如下代码进行测试

        private void Window_Loaded(object sender, RoutedEventArgs e)
{
//@Test 1: valueLocalValue中, BaseValueSource = Local; IsAnnimated = false; IsCoerced = false; IsExpression = false
//@Test 1: LocalValue = 400
object valueLocalValue = ButtonTest.ReadLocalValue(FrameworkElement.WidthProperty);//
ValueSource valueSource = DependencyPropertyHelper.GetValueSource(
ButtonTest,
FrameworkElement.WidthProperty); //@Test 2: afterBindingValueSource.BaseValueSource = Local;
// IsAnnimated = false;
// IsCoerced = false;
// IsExpression = true
//@Test 2: afterBindingLocalValue: BindingExpression 是一个BindingExpression类型,不再是值;
// 其中DataSource= WidhtHeightBindingedClass;
Binding binding = new Binding("Width");
binding.Source = this.WidthHeightSource;
BindingOperations.SetBinding(ButtonTest, WidthProperty, binding); object afterBindingLocalValue = ButtonTest.ReadLocalValue(FrameworkElement.WidthProperty);//
ValueSource afterBindingValueSource = DependencyPropertyHelper.GetValueSource(ButtonTest, FrameworkElement.WidthProperty); BindingOperations.ClearBinding(ButtonTest, WidthProperty);
//@Test 3: afterUnBindingValueSource.BaseValueSource = Default;
// IsAnnimated = false;
// IsCoerced = false;
// IsExpression = false;
//@Test 3: afterUnBindingLocalValue:DependecyProperty.UnsetValue
object afterUnBindingLocalValue = ButtonTest.ReadLocalValue(FrameworkElement.WidthProperty);//
ValueSource afterUnBindingValueSource = DependencyPropertyHelper.GetValueSource(ButtonTest, FrameworkElement.WidthProperty);
}
}

如果,从Test1,2,3中,可以看出,在xaml赋值(等同于后台代码直接赋值)和用Binding来绑定值,只能保存一个值。

1.3 Annimate,BaseValue与Coerce,Validate的区别

动画值要比在BaseValue或者Binding值具有更高的优先权,当前处于动画设置状态的时候,Value值就被设定为动画值;有如下的示例,定义MyButton,其是继承Button,并且在MyButton中定义依赖属性MyDefinedProperty

 public partial class MyButton : Button
    {
        public MyButton()
        {
            InitializeComponent();
        }
        public static readonly DependencyProperty MyDefinedProperty = DependencyProperty.Register("MyDefinded",
    typeof(double),
    typeof(MyButton),
    new FrameworkPropertyMetadata(default(double),
        FrameworkPropertyMetadataOptions.None,
        new PropertyChangedCallback(OnValueChanged),
        new CoerceValueCallback(CoerceValue)),
        new ValidateValueCallback(IsValidateValue)
        );         private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Console.WriteLine("{0} OnValueChanged new value is {1}", d.GetType().ToString(), e.NewValue);
        }         private static object CoerceValue(DependencyObject d, object value)
        {
            Console.WriteLine("{0} CoerceValue value is {1}", d.GetType().ToString(), value);
            return value;
        }         private static bool IsValidateValue(object value)
        {
            Console.WriteLine("MyButton ValidateValue value is {1}", value);
            return true;
        }         public double MyDefinded
        {
            get
            {
                return (double)GetValue(MyDefinedProperty);
            }
            set
            {
                SetValue(MyDefinedProperty, value);
            }
        }
    }

同样,在xaml中定义此类型的Button,并且,定义Trigger,在鼠标移动到按钮上的时候,设置动画,如下代码

<Window x:Class="LocalBaseBindingExpress.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow"
Height="350"
Width="525"
xmlns:loc="clr-namespace:LocalBaseBindingExpress"
Loaded="Window_Loaded">
<Window.Resources>
<Style TargetType="loc:MyButton">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="30"/>
<Style.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter" >
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(loc:MyButton.MyDefinded)"
To="1000" Duration="0:1:5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
<loc:WidthConvertr x:Key="WidthConverter"/>
</Window.Resources>
<Grid>
<loc:MyButton x:Name="ButtonTest"
FontSize="13"
Background="Blue"
Click="ButtonTest_Click" >ButtonSubSub
</loc:MyButton>
</Grid>
</Window>

当我们把鼠标放在按钮上的时候,在调试窗口,可以打印出如下的信息
MyButton ValidateValue value is 65.3535369230769
LocalBaseBindingExpress.MyButton CoerceValue value is 65.3535369230769
LocalBaseBindingExpress.MyButton OnValueChanged new value is 65.3535369230769
MyButton ValidateValue value is 65.3571092307692
LocalBaseBindingExpress.MyButton CoerceValue value is 65.3571092307692
LocalBaseBindingExpress.MyButton OnValueChanged new value is 65.3571092307692
MyButton ValidateValue value is 65.8233815384615
LocalBaseBindingExpress.MyButton CoerceValue value is 65.8233815384615
LocalBaseBindingExpress.MyButton OnValueChanged new value is 65.8233815384615
MyButton ValidateValue value is 66.3182046153846
LocalBaseBindingExpress.MyButton CoerceValue value is 66.3182046153846
LocalBaseBindingExpress.MyButton OnValueChanged new value is 66.3182046153846
MyButton ValidateValue value is 66.8083676923077
LocalBaseBindingExpress.MyButton CoerceValue value is 66.8083676923077
LocalBaseBindingExpress.MyButton OnValueChanged new value is 66.8083676923077
MyButton ValidateValue value is 67.2775246153846
LocalBaseBindingExpress.MyButton CoerceValue value is 67.2775246153846
LocalBaseBindingExpress.MyButton OnValueChanged new value is 67.2775246153846
MyButton ValidateValue value is 67.7459646153846
LocalBaseBindingExpress.MyButton CoerceValue value is 67.7459646153846
LocalBaseBindingExpress.MyButton OnValueChanged new value is 67.7459646153846
MyButton ValidateValue value is 68.2240753846154
LocalBaseBindingExpress.MyButton CoerceValue value is 68.2240753846154
LocalBaseBindingExpress.MyButton OnValueChanged new value is 68.2240753846154
MyButton ValidateValue value is 68.9506415384615
LocalBaseBindingExpress.MyButton CoerceValue value is 68.9506415384615
LocalBaseBindingExpress.MyButton OnValueChanged new value is 68.9506415384615
MyButton ValidateValue value is 69.4235769230769
LocalBaseBindingExpress.MyButton CoerceValue value is 69.4235769230769
LocalBaseBindingExpress.MyButton OnValueChanged new value is 69.4235769230769
MyButton ValidateValue value is 69.9157046153846
LocalBaseBindingExpress.MyButton CoerceValue value is 69.9157046153846
LocalBaseBindingExpress.MyButton OnValueChanged new value is 69.9157046153846
MyButton ValidateValue value is 70.3990276923077
LocalBaseBindingExpress.MyButton CoerceValue value is 70.3990276923077
LocalBaseBindingExpress.MyButton OnValueChanged new value is 70.3990276923077
MyButton ValidateValue value is 70.8701507692308
LocalBaseBindingExpress.MyButton CoerceValue value is 70.8701507692308
LocalBaseBindingExpress.MyButton OnValueChanged new value is 70.8701507692308
MyButton ValidateValue value is 72.0757861538462
LocalBaseBindingExpress.MyButton CoerceValue value is 72.0757861538462
LocalBaseBindingExpress.MyButton OnValueChanged new value is 72.0757861538462

从上边可以看出,依赖属性的值当前是动画形成的值,但是这些值和直接从BaseValue中或者Binding中获取的值一样,都要通过Validate检查和Coerce的检查,然后获得依赖属性的最终值。

1.4 结论

从上边的几个实验来看,依赖属性值的最终的确认,可以用如下的图来描述,下图来自http://www.cnblogs.com/KnightsWarrior/archive/2010/08/27/1809739.html

但是个人认为,可能下图更符合我的思维方式,其中ValueSource的一系列标识量都是为了在程序中获取Value的时候,速度更加快而设计的。

(原创)2. WPF中的依赖属性之二的更多相关文章

  1. WPF中的依赖属性

    1. WPF中的依赖属性 依赖属性是专门基于WPF创建的.在WPF库实现中,依赖属性使用普通的C#属性进行了包装,使用方法与普通的属性是相同的. 1.1 依赖属性提供的属性功能 资源 数据绑定 样式 ...

  2. 在WPF中使用依赖注入的方式创建视图

    在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...

  3. WPF学习笔记——依赖属性(Dependency Property)

    1.什么是依赖属性 依赖属性是一种可以自己没有值,并且通过Binding从数据源获得值(依赖在别人身上)的属性,拥有依赖属性的对象被称为"依赖对象". 依赖项属性通过调用 Regi ...

  4. [No000012D]WPF(5/7)依赖属性

    介绍 WPF带来了很多传统 Windows 应用程序没有的新特性和选择.我们已经讨论了一些 WPF 的特性,是时候更进一步介绍其他特性了.当你读完这个系列之前的文章,我希望你已经或多或少地了解了 WP ...

  5. WPF 精修篇 依赖属性

    原文:WPF 精修篇 依赖属性 依赖属性使用场景 1. 希望可在样式中设置属性. 2. 希望属性支持数据绑定. 3. 希望可使用动态资源引用设置属性. 4. 希望从元素树中的父元素自动继承属性值. 5 ...

  6. ReferentialConstraint 中的依赖属性映射到由存储生成的列

    ReferentialConstraint 中的依赖属性映射到由存储生成的列 这个问题是由于从表中的外键关系建立错误(可能是由于误改),查看从表的所有外键关系,即可找到问题所在. 问题: 什么是从表? ...

  7. Entity Framework问题:ReferentialConstraint 中的依赖属性映射由存储生成的列

    原文:Entity Framework问题:ReferentialConstraint 中的依赖属性映射由存储生成的列 今天在采用Entity Framework 的Database First反向以 ...

  8. dotnetcore3.1 WPF 中使用依赖注入

    dotnetcore3.1 WPF 中使用依赖注入 Intro 在 ASP.NET Core 中默认就已经集成了依赖注入,最近把 DbTool 迁移到了 WPF dotnetcore 3.1, 在 W ...

  9. 【转】WPF中的Binding技巧(二)

    WPF中的Binding技巧(二)     接上篇, 我们来看一看Elementname,Source,RelativeSource 三种绑定的方式 1.ElementName顾名思义就是根据Ui元素 ...

随机推荐

  1. git的一些配置

    git使用socks代理加速 原来git可以配置socks代理的,真好,从github上clone了opencv的代码,基本上是满速了. 首先需要配置shadowsocks,然后通过GUI客户端(或命 ...

  2. a:hover伪类在ios移动端浏览器内无效的解决方法

    a:hover 设置的样式在ios系统的浏览器内显示不出来,看来在iOS系统的移动设备中,需要在按钮元素或body/html上绑定一个touchstart事件才能激活:active状态. 方法 一: ...

  3. vue js moment.js 过滤了双休日和法定节假日

    源码:注!原创的!!!! <template> <div id="DATE"> <ul class="dateForm" @cha ...

  4. 记一次ceph集群的严重故障

    问题:集群状态,坏了一个盘,pg状态好像有点问题[root@ceph-1 ~]# ceph -s    cluster 72f44b06-b8d3-44cc-bb8b-2048f5b4acfe     ...

  5. 关于latex的画图

    可以使用latex画一些简单的图 可以参考这个链接:http://www.latexstudio.net/archives/9400(PGFPlots绘图简易教程[转载])

  6. EOJ 3246 实验室传染病

    线段树,暴力. 先处理出每个点直接能感染到的最左边的和最右边的. 之后每次扩展,看向左能到达的那些点中,最左以及最右能到哪些点,更新. 看向右能到达的那些点中,最左以及最右能到哪些点,更新. 最左最右 ...

  7. 初始Hibernate4

    Hibernate是一个ORM的轻量级框架,解决持久化操作,使得程序员可以从编写繁复的jdbc的工作中解放出来,专注与业务,提高我们的开发效率.移植性. 1.持久化    a) 侠义概念:数据存储在物 ...

  8. Angular Material Starter App

      介绍 Material Design反映了Google基于Android 5.0 Lollipop操作系统的原生应用UI开发理念,而AngularJS还发起了一个Angular Material ...

  9. BZOJ2303 APIO2011方格染色

    这题太神了 首先我们可以发现只有当i和j都是偶数时a[1][1]^a[1][j]^a[i][1]^a[i][j]=1才满足情况,其它时都为0 所以我们可以先把i和j都为偶数的地方^1变为0 下面才是最 ...

  10. 51nod1218 最长递增子序列 V2

    看见标签推荐顺便就做了吧 记$f[i], g[i]$为$i$的含$i$的前缀最长递增子序列和后缀递增子序列 只要满足$f[i] + g[i] == LIS + 1$,那么$i$就是可能的 对于$i$而 ...