二、 依赖属性的优先级

  由于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. 使用CTex完成北京科技大学本科生毕业设计

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  2. Java 后台获取当前时间

    Calendar c = Calendar.getInstance();//可以对每个时间域单独修改 int year = c.get(Calendar.YEAR); int month = c.ge ...

  3. 决策树 -- C4.5算法

    C4.5是另一个分类决策树算法,是基于ID3算法的改进,改进点如下: 1.分离信息   解释:数据集通过条件属性A的分离信息,其实和ID3中的熵:   2.信息增益率   解释:Gain(A)为获的A ...

  4. 【C-分支结构】

    一.关系运算符 双目运算符 自左向右结合 关系运算符的优先级低于算术运算符,高于赋值运算符 <(小于) <=(小于或等于) >(大于) >=(大于或等于) ==(等于) !=( ...

  5. PCFG -- 基于统计方法生成语法树

    语法树的作用 一棵语法树不仅包括了词性(part of speech), 还包括了短语(如名词短语, 动词短语)和结构化的信息(如主语, 谓语和宾语). 这些信息是进行机器翻译所必须的, 例如机器翻译 ...

  6. iptables Data filtering详解

    内容简介防火墙的概述iptables简介iptables基础iptables语法iptables实例案例详解(一)防火墙的简介防火墙是指设置在不同网络或网络安全域之间的一系列部件的组合,它能增强机构内 ...

  7. [转载]sql语句练习50题

    Student(Sid,Sname,Sage,Ssex) 学生表 Course(Cid,Cname,Tid) 课程表 SC(Sid,Cid,score) 成绩表 Teacher(Tid,Tname) ...

  8. Android性能优化典范第一季

    2015年伊始,Google发布了关于Android性能优化典范的专题,一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App.课程专题不仅仅介绍了Android系统中有关 ...

  9. ASP.NET 5系列教程 (一):领读新特性

    近期微软发布了ASP.NET 5.0,本次发布的新特性需求源于大量用户的反馈和需求,例如灵活的跨平台运行时和自主部署能力使ASP.NET应用不再受限于IIS.Cloud-ready环境配置降低了云端部 ...

  10. 关于CAP定理的个人理解

    CAP定理简介 在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer's theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点: 一致性(C ...