WPF入门教程系列十二——依赖属性(二)

2、 依赖属性的优先级编程

  因为WPF 容许咱们能够在多个地方设置依赖属性的值,因此咱们就必需要用一个标准来保证值的优先级别。好比下面的例子中,咱们在三个地方设置了按钮的背景颜色,那么哪个设置才会是最终的结果呢?是Black、Red仍是Azure呢?windows

 

<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>

 

 

 

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

  

  因为这个流程图偏理想化,在实际的工做过程当中咱们会遇到各类各样的问题,我也不可能都碰到,也就没法完全把这些问题说清楚,因此当咱们遇到问题以后,再进行仔细分析,查找缘由,不断总结、触类旁通。oop

3、 依赖属性的继承性能

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

 

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

<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>

 

代码spa

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,因此这个时候继承的值就不会再起做用了。code

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

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

二、有其余更优先级的设置设置了该值,在前面讲的的“依赖属性的优先级”你能够看到具体的优先级别。

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

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

相关文章
相关标签/搜索