转自:http://www.fx114.net/qa-261-90254.aspx

我们应该都知道,XAML是一种声明式语言,XAML的标签声明的就是对象。一个XAML标签会对应着一个对象,这个对象一般会是一个控件类的实例。在.Net平台上,所有类都是引用类型,我们是通过引用来访问对象实例。当一个对象实例不再被任何引用者引用时,它将自动被GC回收。

在WPF开发过程中,后台代码经常会操作前台XAML声明的控件对象实例,这就涉及到如何查找这些控件对象的引用。

有两种方式可以查找前台控件对象的引用,以下分别介绍:

方式1:利用引用者的层级关系来查找控件对象引用

window x:Class="WpfApplication1.Window1"
                         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
                         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                         xmlns:local="clr-namespace:WpfApplication1"
                        Title="WindowServer" Height="300" Width="300" MaxWidth="500" MaxHeight="600" MinHeight="200" MinWidth="200">
                          <StackPanel >

<Button Content="OK" Margin="5" Click="Button_Click"/>
                                        <TextBox  Margin="5,0" Height="100" >
                           </StackPanel>
                </Window>
       以上是用XAML申明了两个控件对象实例,下面后台代码Button控件点击事件器,需要完成对TextBox的内容填字一段字符串。

private void Button_Click(object sender, RoutedEventArgs e)
         {
             StackPanel stackPanel = this.Content as StackPanel;  //this.Content属性引用着StackPanel的实例
             TextBox textBox = stackPanel.Children[1] as TextBox;   //StackPanel实例的Children[1]引用着TextBox实例
             textBox.Text = "Hello,World!";
         }

通过这个关系就可以一路查找下来,同时进行类型的转换。看懂以上关系,那么就很容易知道stackPanel.Childere[0]引用的对象是什么了。

方式2:利用XAML申明的控件引用变量名引用控件对象实例

window x:Class="WpfApplication1.Window1"
                         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
                         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                         xmlns:local="clr-namespace:WpfApplication1"
                        Title="WindowServer" Height="300" Width="300" MaxWidth="500" MaxHeight="600" MinHeight="200" MinWidth="200">
                          <StackPanel >

<Button x:Name="button" Content="OK" Margin="5" Click="Button_Click"/>
                                        <TextBox x:Name="textBox"  Margin="5,0" Height="100" >
                           </StackPanel>
                </Window>
       我们从方式1很容易发现,使用这种方法访问UI上的所有控件对象实例太繁琐了。XAML通过为对象声明引用变量,后台代码通过引用变量就可以直接获取到该对象引用。

而XAML申明对象的引用变量是使用x:Name来做到的。原则上,所有UI控件都存在该属性。

查看以上XAML申明,发现它和方式1唯一的区别是控件了x:Name的引用变量声明。这时,我们的后台代码获取控件对象实例方法如下:

private void Button_Click(object sender, RoutedEventArgs e)
         {
            // StackPanel stackPanel = this.Content as StackPanel;  //this.Content属性引用着StackPanel的实例
             //TextBox textBox = stackPanel.Children[1] as TextBox;   //StackPanel实例的Children[1]引用着TextBox实例
             textBox.Text = "Hello,World!";
         }

这段代码通过XAML申明的对象引用变量直接访问对象,相对方式1确实简洁多了,呵呵。那么如何我们需要访问Button对象呢,当然直接使用button就OK了。

这里需要提一点,x:Name申明对象引用变量的同时,如果控件存在Name属性,那么采用x:Name将一举两得,可自动对Name属性赋值,赋值的名称当然与引用变量名称相同。所以,建议使用x:Name,因为它的功能已涵盖了控件的Name属性功能,可以增强代码的统一性和可读性。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

后台代码除了经常访问前台XAML声明的控件对象实例,还会经常访问前台声明的控件资源。

看一下以下这段XAML申明:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    Title="WindowServer" Height="300" Width="300" MaxWidth="500" MaxHeight="600" MinHeight="200" MinWidth="200">
    <Window.Resources>
        <sys:String x:Key="myString">Hello,World!</sys:String>
    </Window.Resources>
    <StackPanel>

<Button x:Name="button1" Content="Send Command" Margin="5" Click="Button_Click" >
        <TextBox x:Name="textBoxA" Margin="5,0" Height="100" >
    </StackPanel>
 </Window>

这段XAML声明和之前的没什么区别,除了黑体字部分。这段申明是向Window.Resources资源字典添加一个条目,条目的内容是一段字符串。

再仔细观察,你会发现除了字符串,还有x:Key="myString"这一语句。它的作用是干嘛呢,很简单是建立资源字典的键值对,方便索引资源条目。如何使用过C++的STL,对Map应该就不陌生。这个x:Key就相当于Map的key。下面看一看,后台代码如何访问这段字符串。

private void Button_Click(object sender, RoutedEventArgs e)
         {
                string str = this.FindResource("myString") as string;  //调用一个拥有Resource属性对象的FindResource方法就可以从资源字典里检索资源

this.textBox.Text = str;

}

值得注意一下,检索资源返回的是Object对象,需要根据相应类型转换即可。

除了后台代码经常检索控件资源,前台控件也可能会访问该资源,引用的方法是使用StaticResource或DynamicResource.

下面的示例在page的根元素定义了一个SolidColorBrush画刷作为一个资源,并展示如何用它来设置Page中子元素的属性
<Page Name="root"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

<Page.Resources>
    <SolidColorBrush x:key=”MyBrush” Color=”Gold”/>
    <Style TargetType=”Border” x:Key=”PageBackground”>
       <Setter Property=”Background” Value=”Blue”/>
    </Style>
<Page.Resources>
    <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
    <Style TargetType="Border" x:Key="PageBackground">
      <Setter Property="Background" Value="Blue"/>
    </Style>
   
</Page.Resources>
 <StackPanel>
    <DockPanel>
        <Button DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
              </DockPanel>
 </StackPanel>
</Page>
 
每个框架级别的元素(FrameworkElement或FrameworkContentElement)都有一个Resources属性,我们可以在任何元素上定义资源,不过习惯上在根元素上定义,如上面 的XAML代码中<Page.Resources/>定义资源。
       通过属性x:Key给每个资源赋予一个唯一的关键字。这样我们就可以在XAML的其它地方通过Key值来操作对应的资源了。如下示例,使用资源给元素的属性赋值
<Button Background=”{StaticResource MyBrush}” />
 
StaticResource 和DynamicResource的区别:
 
资源可以被当作StaticResource和DynamicResource两种类型来引用。

当引用资源时,下面的考虑将影响你是选择StaticResource还是DynamicResource来它。
1〉 如何为应用程序创建资源(资源是在一个Page中,在APP范围还是在松散的Xaml中或仅仅在程序集中)
2〉 应用程序功能:是否在运行时改变资源
3〉 每个资源引用类型不同的寻找行为
StaticResources
StaticResources在如下情况下使用比较好
1〉 在资源第一次引用之后无需再修改资源的值
2〉 StaticResource引用不会基于运行时的行为进行重新计算。比如在重新加载Page的时候。
3〉 当需要设置的属性不是DependencyObject或Freezable类型的时候,需要用staticResource
4〉 当需要将资源编译到dll中,并打包为程序的一部份,或者希望在各应用程序之间共享
5〉 当需要为一个自定义控件创建一个theme,并theme中使用资源,就需要使用StaticResource。因为StaticResource的资源查找行为时可预测的,并且本身包含在theme中。而对于DynamicResource,即使资源是定义在theme中,也只能等到运行时确定,导致一些可能意料不到的情况发生。
6〉 当需要使用资源设置大量的依赖属性的时候(dependency property),依赖属性具有属性系统提供的值缓存机制,所以如果能在程序装载时设置依赖属性的值,依赖属性就不需要检查自己的值并返回最后的有效值了。可以获得显示时的好处。
Static resource 查询行为
1〉 查找使用该资源的元素的resource字典
2〉 顺逻辑树向上查找父元素的资源字典,直到根节点
3〉 查找Application资源
4〉 不支持向前引用。即不能引用在引用点之后才定义的资源
 
Dynamic Resource
Dynamic resources一般使用在如下场合
1〉 资源的值依赖一些条件,而该条件直到运行时才能确定。这包括系统资源,或是用户可设置的资源。例如,可以创建引用系统属性诸如SystemColors,SystemFonts来设置值,这些属性是动态的,他们的值来自于运行环境和操作系统
2〉 为自定义控件引用或创建theme style
3〉 希望在程序运行期间调整资源字典的内容
4〉 希望资源可以向前引用
5〉 资源文件很大,希望在运行时加载
6〉 要创建的style的值可能来自于其它值,而这些值又依赖于themes或用户设置
7〉 当引用资源的元素的父元素有可能在运行期改变,这个时候也需要使用动态资源。因为父元素的改变将导致资源查询的范围。
Dynamic resource 查询行为
1〉 查找使用该资源的元素的resource字典
如果元素定义了一个Style 属性,将查找Style中的资源字典
如果元素定义了一个Template属性,将查找FrameworkTemplate中的资源字典
2〉 顺逻辑树向上查找父元素的资源字典,直到根节点
3〉 查找Application资源
4〉 查找当前激活状态下的theme资源字典。
5〉 查找系统资源
Dynamic resource的限制条件
1〉 属性必须是依赖属性,或是Freezable的

笔记04 WPF对象引用的更多相关文章

  1. 笔记04 WPF的Binding

    oneWay:使用 OneWay 绑定时,每当源发生变化,数据就会从源流向目标. OneTime: 绑定也会将数据从源发送到目标:但是,仅当启动了应用程序或 DataContext 发生更改时才会如此 ...

  2. JS自学笔记04

    JS自学笔记04 arguments[索引] 实参的值 1.对象 1)创建对象 ①调用系统的构造函数创建对象 var obj=new Object(); //添加属性.对象.名字=值; obj.nam ...

  3. JAVA自学笔记04

    JAVA自学笔记04 1.switch语句 1)格式:switch(表达式){ case 值1: 语句体1; break; case 值2: 语句体2; break; - default: 语句体n+ ...

  4. 机器学习实战(Machine Learning in Action)学习笔记————04.朴素贝叶斯分类(bayes)

    机器学习实战(Machine Learning in Action)学习笔记————04.朴素贝叶斯分类(bayes) 关键字:朴素贝叶斯.python.源码解析作者:米仓山下时间:2018-10-2 ...

  5. CS229 笔记04

    CS229 笔记04 Logistic Regression Newton's Method 根据之前的讨论,在Logistic Regression中的一些符号有: \[ \begin{eqnarr ...

  6. 【HLSL学习笔记】WPF Shader Effect Library算法解读之[DirectionalBlur]

    原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[DirectionalBlur] 方位模糊是一个按照指定角度循环位移并叠加纹理,最后平均颜色值并输出的一种特效. ...

  7. 【HLSL学习笔记】WPF Shader Effect Library算法解读之[Embossed]

    原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[Embossed] Embossed(浮雕效果)          浮雕效果主要有两个参数:Amount和Wid ...

  8. 【HLSL学习笔记】WPF Shader Effect Library算法解读之[BandedSwirl]

    原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[BandedSwirl] 因工作原因,需要在Silverlight中使用Pixel Shader技术,这对于我来 ...

  9. SaToken学习笔记-04

    SaToken学习笔记-04 如果有问题,请点击:传送门 角色认证 在sa-token中,角色和权限可以独立验证 // 当前账号是否含有指定角色标识, 返回true或false StpUtil.has ...

随机推荐

  1. ABP数据库的迁移

    添加表,一(Test)对多(Test1)关系 Test using Abp.Domain.Entities.Auditing; using System; using System.Collectio ...

  2. UITabBarController支持旋转

    1.默认的UITabBarController不支持四个方向,但可以给UITabBarController增加一个类别,实现旋转:具体做法: 在工程添加一个.h和.m文件如下: //Rotation. ...

  3. 微信小程序答题系统实现随机出题 答题小程序如何实现随机出题 微信小程序 答题系统

    最近头脑王者非常火爆,公司也在开发类似头脑王者的答题系统,这个重任交到我这边来了,我们在开发的这个微信小程序答题系统,需要实现随机出题.尤其是一些比如闯关的环节,需要随机从题库里抽取若干道题目,给到用 ...

  4. social-auth-app-django模块

    一 原文地址:http://www.cnblogs.com/adc8868/p/7665864.html social-auth-app-django模块是专门用于Django的第三方登录OAuth2 ...

  5. Red is good(bzoj 1419)

    Description 桌面上有R张红牌和B张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付出1美元.可以随时停止翻牌,在最优策略下平均能得到多少钱. Input 一 ...

  6. Linux System Programming 学习笔记(九) 内存管理

    1. 进程地址空间 Linux中,进程并不是直接操作物理内存地址,而是每个进程关联一个虚拟地址空间 内存页是memory management unit (MMU) 可以管理的最小地址单元 机器的体系 ...

  7. 【NOIP2016】换教室(DP,期望)

    题意: 对于刚上大学的牛牛来说, 他面临的第一个问题是如何根据实际情况中情合适的课程. 在可以选择的课程中,有2n节课程安排在n个时间段上.在第 i ( 1≤ i≤n)个时同段上, 两节内容相同的课程 ...

  8. AC日记——[SDOI2011]染色 洛谷 P2486

    题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例#1: 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C ...

  9. 富文本ZSSRichTextEditor之趟坑集锦

    富文本ZSSRichTextEditor是iOS原生与网页交互的集大成者,各种交互.自然问题也是多多,这篇文文章陆续更新遇到的奇葩问题. 1.问题1:从头条这种文章里头复制粘贴的文章,里边有图片,我们 ...

  10. python学习之-- 生成唯一ID

    以下以2种方法生成唯一ID def uuid_method(): """第一种方法""" import uuid return str(uu ...