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. 洛谷P1803凌乱的yyy 题解

    题目传送门 这道题也是贪心思想.先排序一遍(按照结束的时间排)在进行扫描,满足条件的直接保存,增加ans,最后输出即可. #include<bits/stdc++.h> using nam ...

  2. [笔记] 几个前端bug的解决方案

    jQuery UI下被拖动的元素上飘 症状出现在几乎所有浏览器里.使用 1.10.x 的draggable,在滚动栏下移(即非处于页面顶部)的时候拖动draggable的元素,它会向上跳一段距离.解决 ...

  3. hdu4796

    4月真是没写啥题,这题还是月初写的…… 不错的插头dp,首先由n和m的范围知肯定是轮廓线是横向划的 问题的难点在于怎么处理下面两个问题 1.怎么处理独立插头 2.怎么处理完全将W和L左右隔开 先说独立 ...

  4. 【51nod】1227 平均最小公倍数

    题解 这个故事告诉们数论函数不要往分式上跑,你推不出来 好久没推式子了这么明显的转化我都忘了= = 首先\(A(n) = \frac{1}{n} \sum_{i = 1}^{n} \frac{i * ...

  5. CentOS7.5 firefox Flash插件更新

    CentOS7自带的firefox没有flash插件,所以是没有办法在网页上看视频的,需要自己手动安装 1.下载 打开flash官网https://get.adobe.com/flashplayer/ ...

  6. JavaScript 实现数组去重

    JavaScript 实现数组去重 演示Demo 数组去重 // 方法一 function unique1(a) { var res = []; for (var i = 0, len = a.len ...

  7. thinkphp5.0动态配置

    设置配置参数 使用set方法动态设置参数,例如: Config::set('配置参数','配置值'); // 或者使用助手函数 config('配置参数','配置值'); 也可以批量设置,例如: Co ...

  8. Python类总结-字段,方法,属性区别及StaticMethod, Property,私有字段和私有属性

    类包含下列 静态属性 动态属性 静态方法 动态方法 class Province: #静态字段--属于类,调用方法类.字段名 memo = "中国23个省之一" #动态字段--属于 ...

  9. 【小思考】Python里面有声明和定义分离这一说么?

    第一部分: 探究这个问题,还是因为编程的时候碰到了这个错误: 提示tcplink没有定义,tcplink是我自己写的一个给监听到的tcp连接请求分配新线程的函数,不过是写在了下面,就像这样: 如果是C ...

  10. RxSwift 系列(九)

    前言 看完本系列前面几篇之后,估计大家也还是有点懵逼,本系列前八篇也都是参考RxSwift官方文档和一些概念做的解读.上几篇文章概念性的东西有点多,一时也是很难全部记住,大家脑子里面知道有这么个概念就 ...