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. fedora安装后的配置

    fedora安装后的一些配置 (mirror)源 换源 默认从fedora官网下载太慢,考虑换用国内的源(镜像站点),推荐中科大.阿里云.浙大.网易等的源. 比如我用浙大ZJU的源http://mir ...

  2. git - git命令中文显示乱码

    使用git add添加要提交的文件的时候,如果文件名是中文,会显示形如897\232\350\256...的乱码,解决办法:   git config --global core.quotepath ...

  3. AC日记——#2057. 「TJOI / HEOI2016」游戏 LOJ

    #2057. 「TJOI / HEOI2016」游戏 思路: 最大流: 代码: #include <cstdio> #include <cstring> #include &l ...

  4. 【C#】编码史记

    计算机中的字是如何处理的? 如果你用放大镜看一下,可以看出屏幕上的字是由一个一个的像素点组成的,每一个字符用一组像素点拼接出来,这些像素点组成一幅图像,变成了我们的文字,计算机又是如何将我们的文字保存 ...

  5. 洛谷P1438 无聊的数列 [zkw线段树]

    题目传送门 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个数列{a[i]} ...

  6. BZOJ4327 [JSOI2012] 玄武密码 [AC自动机]

    题目传送门 玄武密码 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神 ...

  7. Jenkins多选项框使用

    多选框的使用场景还是挺多的,比如发布多个服务,或者选择哪些服务器 想要使用多选项,则需要安装插件extend choice parameter,然后在项目中配置参数化构建过程 配置完上面,我们就可以在 ...

  8. FutureTask简单实战

    FutureTask是什么? 线程池的实现核心之一是FutureTask.在提交任务时,用户实现的Callable实例task会被包装为FutureTask实例ftask:提交后任务异步执行,无需用户 ...

  9. urllib2 调用salt restapi

    1获取token #_*_coding:utf8_*_ import urllib2 import json def get_token(): url='http://10.20.32.86:8000 ...

  10. WSDL语法

    <什么是WSDL语言> WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及 ...