转自: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. iOS-----5分钟学会枚举的正确使用姿势-Enumeration宏

    前言 Enum,枚举,相信大部分编程语言都有对应的枚举类型,功能可能有多有少,但是枚举最核心的功能是 “规范的定义代码中的状态.状态码.选项”. 状态.状态码.选项 什么是状态:同时只能出现一个值(状 ...

  2. 【Luogu】P3979遥远的国度(树链剖分)

    题目链接 不会换根从暑假开始就困扰我了……拖到现在…… 会了还是很激动的. 换根操作事实上不需要(也不能)改树剖本来的dfs序……只是在query上动动手脚…… 设全树的集合为G,以root为根,u在 ...

  3. BZOJ-2829 信用卡凸包

    凸包题. 我们先把所有信用卡的四个定点的坐标求出来,然后计算凸包长度,最后加上一个圆的周长就行. #include <cstdlib> #include <cstdio> #i ...

  4. [luoguP3355] 骑士共存问题(二分图最大独立集)

    传送门 模型 二分图最大独立集,转化为二分图最大匹配,从而用最大流解决. 实现 首先把棋盘黑白染色,使相邻格子颜色不同. 把所有可用的黑色格子看做二分图X集合中顶点,可用的白色格子看做Y集合顶点. 建 ...

  5. [中山市选]杀人游戏 (Tarjan缩点)

    题目链接 Solution 可以考虑到如果知道环内一点的身份,如果凶手在其中就查出来了,同时不会有危险. 那么对警察造成威胁的就是那些身份不明且不能从其他点转移过来的点. 那么大部答案就是缩完点之后入 ...

  6. iOS-通信录

    1.概述: * 对于每一个移动设备而言,都有一个内置的数据库-----通讯录. * 在IOS上,通讯录放在SQLite3数据库中. * 由于不同应用之间不能直接访问,我们想要实现对数据库的访问,必须使 ...

  7. 理解 Glance

    OpenStack 由 Glance 提供 Image 服务. 理解 Image 要理解 Image Service 先得搞清楚什么是 Image 以及为什么要用 Image? 在传统 IT 环境下, ...

  8. Django ConnectionAbortedError WinError 10053 错误

    因为ajax默认是异步提交,可是有时候我们会发现,本来要求请求马上出现,可是异步会导致后面突然再执行,这样就出问题了. (1)添加这样一段代码 $.ajaxSetup({ async : false ...

  9. 标准C程序设计七---106

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...

  10. linux sleep函数

    应用程序: #include usleep(n) //n微秒 Sleep(n)//n毫秒 sleep(n)//n秒 驱动程序: #include mdelay(n) //milliseconds 其实 ...