二、 依赖属性的优先级

  由于WPF 允许我们可以在多个地方设置依赖属性的值,所以我们就必须要用一个标准来保证值的优先级别。比如下面的例子中,我们在三个地方设置了按钮的背景颜色,那么哪一个设置才会是最终的结果呢?是Black、Red还是Azure呢?

<Window x:Class="WpfApp1.WindowDepend"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="WindowDepend" Height="400" Width="400">

    <Grid>

        <Button x:Name="myButton" Background="Azure">

            <Button.Style>

                <Style TargetType="{x:Type Button}">

                    <Setter Property="Background" Value="Black"/>

                    <Style.Triggers>

                        <Trigger Property="IsMouseOver" Value="True">

                            <Setter Property="Background" Value="Red" />

                        </Trigger>

                    </Style.Triggers>

                </Style>

            </Button.Style>

            Click

        </Button>

    </Grid>

</Window>

通过前面的简单介绍,我们了解了简单的依赖属性,每次访问一个依赖属性,它内部会按照下面的顺序由高到底处理该值。详细见下图

  由于这个流程图偏理想化,在实际的工作过程中我们会遇到各种各样的问题,我也不可能都碰到,也就无法彻底把这些问题说清楚,所以当我们遇到问题之后,再进行仔细分析,查找原因,不断总结、举一反三。

三、 依赖属性的继承

  属性值继承是 Windows Presentation Foundation (WPF) 属性系统的一项功能。 属性值继承使元素树中的子元素可以从父元素那里获取特定属性的值,并继承该值,就好像它是在最近的父元素中的任意位置设置的一样。 父元素还可以通过属性值继承来获得其值,因此系统有可能一直递归到页面根元素。 属性值继承不是属性系统的默认行为;属性必须用特定的元数据设置来建立,以便使该属性能够对子元素启动属性值继承。

依赖属性继承的最初意愿是父元素的相关设置会自动传递给所有层次的子元素 ,即元素可以从其在树中的父级继承依赖项属性的值。这个我们在编程当中接触得比较多,如当我们修改窗体父容器控件的字体设置时,所有级别的子控件都将自动 使用该字体设置 (前提是该子控件未做自定义设置)。接下来,我们来做一个实际的例子。代码如下:

<Window x:Class="WpfApp1.WindowInherited"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="WindowInherited" Height="400" Width="500" Loaded="Window_Loaded" >

    <Grid>

        <Grid.RowDefinitions>

            <RowDefinition Height="101*"/>

            <RowDefinition Height="80"/>

            <RowDefinition Height="80"/>

        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" >

            <Label Content="继承自Window的FontSize" />

            <TextBlock Name="textBlockInherited" Text="重写了继承,没有继承Window的FontSize"

               FontSize="36" TextWrapping="WrapWithOverflow"/>

            <StatusBar>没有继承自Window的FontSize,Statusbar</StatusBar>

        </StackPanel>

        <WrapPanel Grid.Row="1">

            <Label Content="窗体字体大小" />

            <ComboBox Name="drpWinFontSize"></ComboBox>

            <Button Name="btnFontSize" Click="btnFontSize_Click">改变window字体</Button>

        </WrapPanel>

        <WrapPanel Grid.Row="2">

            <Label Content="文本字体大小" />

            <ComboBox Name="drpTxtFontSize"></ComboBox>

            <Button Name="btnTextBlock" Click="btnTextBlock_Click">改变TextBlock字体</Button>

        </WrapPanel>

    </Grid>

</Window>

代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Shapes;

namespace WpfApp1

{

    /// <summary>

    /// WindowInherited.xaml 的交互逻辑

    /// </summary>

    public partial class WindowInherited : Window

    {

        public WindowInherited()

        {

            InitializeComponent();

        }

        private void btnFontSize_Click(object sender, RoutedEventArgs e)

        {

            this.FontSize =Convert.ToInt32(drpWinFontSize.Text);

        }

        private void btnTextBlock_Click(object sender, RoutedEventArgs e)

        {

            this.textBlockInherited.FontSize = Convert.ToInt32(drpTxtFontSize.Text);

        }

        private void Window_Loaded(object sender, RoutedEventArgs e)

        {

            List<int> listFontSize = new List<int>();

            for (int i = 0; i <= 60; i++)

            {

                listFontSize.Add(i + 4);

            }

            drpTxtFontSize.ItemsSource = listFontSize;

            drpWinFontSize.ItemsSource = listFontSize;

        }

    }

}

效果图如下:

  Window.FontSize 设置会影响所有的内部元素字体大小,这就是所谓的属性值继承,如上面代码中的第一个Label没有定义FontSize ,所以它继承了Window.FontSize的值。但一旦子元素提供了显式设置,这种继承就会被打断,如第二个TextBlock定义了自己的 FontSize,所以这个时候继承的值就不会再起作用了。

  这个时候你会发现一个很奇怪的问题:虽然StatusBar没有重写FontSize,同时它也是Window的子元素,但是它的字体大小却没 有变化,保持了系统默认值。那这是什么原因呢?作为初学者可能都很纳闷,官方不是说了原则是这样的,为什么会出现表里不一的情况呢?其实仔细研究才发现并 不是所有的元素都支持属性值继承。还会存在一些意外的情况,那么总的来说是由于以下两个方面:

1、有些Dependency属性在用注册的时候时指定Inherits为不可继承,这样继承就会失效了。

2、有其他更优先级的设置设置了该值,在前面讲的的“依赖属性的优先级”你可以看到具体的优先级别。

属性值继承通过混合树操作。持有原始值的父对象和继承该值的子对象都必须是 FrameworkElementFrameworkContentElement,且都必须属于某个逻辑树。 但是,对于支持属性继承的现有 WPF 属性,属性值的继承能够通过逻辑树中没有的中介对象永久存在。 这主要适用于以下情况:让模板元素使用在应用了模板的实例上设置的所有继承属性值,或者使用在更高级别的页级成分(因此在逻辑树中也位于更高位置)中设置的所有继承属性值。 为了使属性值的继承在这两种情况下保持一致,继承属性必须注册为附加属性。

  这里的原因是部分控件如StatusBar、Tooptip和Menu等内部设置它们的字体属性值以匹配当前系统。这样用户通过操作系统的控制 面板来修改它们的外观。这种方法存在一个问题:StatusBar等截获了从父元素继承来的属性,并且不影响其子元素。比如,如果我们在 StatusBar中添加了一个Button。那么这个Button的字体属性会因为StatusBar的截断而没有任何改变,将保留其默认值。所以大家 在使用的时候要特别注意这些问题。

WPF入门教程系列十二——依赖属性(二)的更多相关文章

  1. WPF入门教程系列十四——依赖属性(四)

    六.依赖属性回调.验证及强制值 我们通过下面的这幅图,简单介绍一下WPF属性系统对依赖属性操作的基本步骤: 借用一个常见的图例,介绍一下WPF属性系统对依赖属性操作的基本步骤: 第一步,确定Base ...

  2. WPF入门教程系列十八——WPF中的数据绑定(四)

    六.排序 如果想以特定的方式对数据进行排序,可以绑定到 CollectionViewSource,而不是直接绑定到 ObjectDataProvider.CollectionViewSource 则会 ...

  3. WPF入门教程系列十六——WPF中的数据绑定(二)

    三.绑定模式 通过上一文章中的示例,学习了简单的绑定方式.在这里的示例,要学习一下绑定的模式,和模式的使用效果. 首先,我们来做一个简单示例,这个示例是根据ListBox中的选中项,去改变TextBl ...

  4. WPF入门教程系列十五——WPF中的数据绑定(一)

    使用Windows Presentation Foundation (WPF) 可以很方便的设计出强大的用户界面,同时 WPF提供了数据绑定功能.WPF的数据绑定跟Winform与ASP.NET中的数 ...

  5. WPF入门教程系列十九——ListView示例(一)

    经过前面的学习,今天我做一个比较综合的WPF程序示例,主要包括以下功能: 1) 查询功能.从数据库(本地数据库(local)/Test中的S_City表中读取城市信息数据,然后展示到WPF的Windo ...

  6. WPF入门教程系列十——布局之Border与ViewBox(五)

    九. Border Border 是一个装饰的控件,此控件绘制边框及背景,在 Border 中只能有一个子控件,若要显示多个子控件,需要将一个附加的 Panel 控件放置在父 Border 中.然后可 ...

  7. WPF入门教程系列二十三——DataGrid示例(三)

    DataGrid的选择模式 默认情况下,DataGrid 的选择模式为“全行选择”,并且可以同时选择多行(如下图所示),我们可以通过SelectionMode 和SelectionUnit 属性来修改 ...

  8. WPF入门教程系列二——Application介绍

    一.Application介绍 WPF和WinForm 很相似, WPF与WinForm一样有一个 Application对象来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只 ...

  9. WPF入门教程系列(二) 深入剖析WPF Binding的使用方法

    WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProp ...

随机推荐

  1. Opacity多浏览器透明度兼容处理

    用来设定元素透明度的 Opacity 是CSS 3里的一个属性.当然现在还只有少部分浏览器支持. 不过各个浏览器都有自己的私有属性来支持,其中包括老版本的Mozilla和Safari: IE: fil ...

  2. Titanium系列--对Window和View的一点理解

    1. window相当于一块屏幕,view相当于一个div层.window拥有全屏和模态化属性,view则没有这2个属性. 2. 创建一个window作为我们的APP的屏幕,之后我们将添加其他元素来丰 ...

  3. init.css

    [24/7金,15] Mon Feb 29 2016 16:29:25 GMT+0800 yahoo.css.yahari @charset "utf-8"; /*yahoo*/ ...

  4. linux shell

    1.+到n for i in {1..n}doa=$(($a+$i))doneecho $a 2. 写一个脚本.输入如下效果 0 01 012 0123 01234 012345 0123456 01 ...

  5. mongodb安装及基础命令

    安装mongodb(mongodb-linux-x86_64-3.2.4.tgz)1 export PATH=$PATH:/usr/local/mongodb/bin2 /usr/local/mong ...

  6. vb- ----之常用函数

    [VB]常用函数 2007-10-25 10:52 3375人阅读 评论(1) 收藏 举报 vbstringdateintegervbscriptwindows (一)类型转换类函数1. CType( ...

  7. VS2012下配置OpenCV2.4.5

    最近在折腾了一下VS2012的OpenCVS2.4.5配置,同VS2010下基本相同,做个简单的记录,以备日后查阅. 1. 安装OpenCV 从OpenCV官网:http://opencv.org/下 ...

  8. Hbase随笔2

    Hbase是建立在HDFS上的分布式数据库,下图是Hbase表的模型: Hbase这个数据库其实和传统关系数据库还是有很多类似之处,而不是像mongodb,memcached以及redis完全脱离了表 ...

  9. solr&lucene3.6.0源码解析(四)

    本文要描述的是solr的查询插件,该查询插件目的用于生成Lucene的查询Query,类似于查询条件表达式,与solr查询插件相关UML类图如下: 如果我们强行将上面的类图纳入某种设计模式语言的话,本 ...

  10. Win7系统修改hosts文件不能保存的解决方法

    地址:http://jingyan.baidu.com/album/e5c39bf56564a539d7603312.html