二、 依赖属性的优先级

  由于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. angular中的自定义过滤器

    <!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="C ...

  2. easyui 》 radio取值,checkbox取值,select取值,radio选中,checkbox选中,select选中

    获取一组radio被选中项的值var item = $('input[@name=items][@checked]').val();获取select被选中项的文本var item = $(" ...

  3. [java基础]java跨平台的基础知识

    1.Javac编译器 Javac编译器读取Java源代码,并将其编译成字节代码(.class格式),调用Javac的命令行示例如下: C:>javac options filename.java ...

  4. Bookstore project using XAMPP 详细配置 Part 1

    这是学校的一个project,记录在这里,以备复习.主要是用XAMPP通过phpMyAdmin连接MySQL数据库,实现一个简单的查询功能. Outline Setup of XAMPP Implem ...

  5. 解决 504 Gateway Time-out和502 Bad Gateway(nginx)

    504 Gateway Time-out 问题所在: 所请求的网关没有请求到,简单来说就是没有请求到可以执行的PHP-CGI. 一般看来, 这种情况可能是由于nginx默认的fastcgi进程响应的缓 ...

  6. TextView支持的XML属性及相关方法

    1.android:auyoLink----->setAutoLinkMask(int) ----->是否将符合指定格式的文字转换为可单击的超链接形式 2.android:autoText ...

  7. myeclipse导入项目出现乱码

    (1)修改整个工作空间的编码方式: Window->Preferences->General->Workspace->Text file Encoding 在 Others 里 ...

  8. 转:给 C# 开发者的代码审查清单

      给 C# 开发者的代码审查清单   [感谢@L就是L 的热心翻译.如果其他朋友也有不错的原创或译文,可以尝试推荐给伯乐在线.] 这是为C#开发者准备的通用性代码审查清单,可以当做开发过程中的参考. ...

  9. ieee80211w

    80211w概述 1, WLAN网络在设计的时候就容易遭受各种类型的Denial of Service(DOS)攻击, a, 射频干扰(RF jamming) b, Spoofed Disconnec ...

  10. Linux常用目录