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. find tar排除指定文件或目录操作及查找文件内容关键字

    1.find查找排除单个目录 查找当前目录或者子目录下所有.txt文件,但是跳过子目录sk find . -path "./sk" -prune -o -name "*. ...

  2. 关于Android不同系统版本的市场占比情况详解

    一,google官方统计的不同Android版本市场的占比强开 google统计的数据情况 这个是google官方对于不同版本的市场占比情况.这个是针对全世界所有的Android手机占比情况. 二,友 ...

  3. beego orm操作mysql数据库

    慢慢弄起来~~ 按官方操作文档试一下. 那个err重复和user编号问题,以后再弄.. package main import ( "fmt" "github.com/a ...

  4. java SE :文件基本处理 File、FileFilter、FileNameFilter

    File    对目录及文件的创建.重命名.删除.文件列表.判断是否存在 构造函数 // 完整的目录或文件路径 public File(String pathname) //父级目录/文件路径+子级目 ...

  5. 如何才能通俗易懂地解释JS中的的"闭包"?

    看了知乎上的话题 如何才能通俗易懂的解释javascript里面的‘闭包’?,受到一些启发,因此结合实例将回答中几个精要的答案做一个简单的分析以便加深理解. 1. "闭包就是跨作用域访问变量 ...

  6. Mac 命令行美化

    在 mac 中使用原生的命令行工具,竟然没有 git 命令的自动补全,在 git 仓库下也看不到当前的分支名,不能忍.于是,开始一波改造. 目标:命名 Tab 自动补全:可以显示分支名: 一番 Goo ...

  7. mysql正则查询 模糊查询

    -- ==============正则查询================ /* SQL默认是忽略大小写的 正则模式使用REGEXP和NOT REGEXP操作符(或RLIKE和NOT RLIKE,它们 ...

  8. debug id

    id是Eclipse的debugger自己生成的,用于告诉你哪些变量是指向同一个对象:id相同即指向同一个对象. primitive不是对象,所以就没有id. 但是如果你用primitive的wrap ...

  9. 什么情况下调用doGet()和doPost()?

    Jsp页面中的FORM标签里的method属性为get时调用doGet(),为post时调用doPost().

  10. XamarinForms教程构建XamarinForms开发环境

    构建XamarinForms开发环境 所谓Xamarin.Forms的开发环境,就是指在基本硬件和数字软件的基础上,为支持系统软件和应用软件的工程化开发和维护而使用的一组软件,简称SDE.对于任何的程 ...