WPF之XMAL对象引用总结

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

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

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

           方式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>
       以上是用XMAL申明了两个控件对象实例,下面后台代码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:利用XMAL申明的控件引用变量名引用控件对象实例

       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上的所有控件对象实例太繁琐了。XMAL通过为对象声明引用变量,后台代码通过引用变量就可以直接获取到该对象引用。

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

     查看以上XMAL申明,发现它和方式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!";
         }

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

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

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

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

       看一下以下这段XMAL申明:

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

     这段XMAL声明和之前的没什么区别,除了黑体字部分。这段申明是向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属性,我们可以在任何元素上定义资源,不过习惯上在根元素上定义,如上面 的xmal代码中<Page.Resources/>定义资源。
       通过属性x:Key给每个资源赋予一个唯一的关键字。这样我们就可以在Xmal的其它地方通过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的

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值