zoukankan      html  css  js  c++  java
  • Name和x:Name

     

    x:Name:一个是可视树,Name:一个是逻辑树属性 都是指向某个元素异曲同工 官方解释: x:Name: 唯一标识对象元素,以便于从代码隐藏或通用代码中访问实例化的元素。x:Name 一旦应用于支持编程模型,便可被视为与由构造函数返回的用于保存对象引用的变量等效。 Name: 获取或设置元素的标识名称。该名称提供一个引用,以便当 XAML 处理器在处理过程中构造标记元素之后,代码隐藏(如事件处理程序代码)可以对该元素进行引用。这是一个依赖项属性。   有些 WPF 框架级别的应用程序可能能够完全避免使用 x:Name 属性,因为在 WPF 命名空间内为几个重要基类(如 FrameworkElement/FrameworkContentElement)指定的 Name 依赖项属性也具有此用途。仍然有一些常见的 XAML 以及框架方案需要在不使用 Name 属性的情况下通过代码访问元素,这种情况在某些动画和演示图板支持类中最为突出。例如,您应当在时间线以及在 XAML 中创建的转换上指定 x:Name,前提是您计划在代码中引用它们。   如果 Name 可用作类的一个属性,则 Name 和 x:Name 可作为属性互换使用,但如果在同一元素上同时指定了这两者,则将产生错误。

    大家都知道,XAML是“用来设计UI”的,设计师用XAML设计出来的UI其后台代码(程序逻辑)可以由程序员用C#或者VB去写——这叫做Code-behind。实际上,设计师用XAML和程序用C#都是在构建同一个类,换句话说就是:把一个类劈成两半,与UI相关的那半由设计师用XAML写,与逻辑相关的那半由程序员用C#写。
    .NET之所以支持这种劈开写的功能,得益于partial这个关键字。请大家看这两段代码
    // For UI public partial class Car { Color bodyColor; Color windowColor; Polygon door; Polygon seat; }
    // For logic public partial class Car { public void Accelerate() { /*80, 90... 120, 140....1200...flying...*/} public void Break() {/*zizizizizizizizizi....*/ } } public class Car { // UI Color bodyColor; Color windowColor; Polygon door; Polygon seat;
    // logic public void Accelerate() { /*80, 90... 120, 140....1200...flying...*/} public void Break() {/*zizizizizizizizizi....*/ } } 实际效果是完全一样的。只是前者是把UI和逻辑劈开写,后者是混在一起写罢了。
    劈开的确是劈开了,但让设计师用C#代码去实现UI恐怕不现实——让Blend直接生成C#不是不可能是事情,只是C#描述UI太不直观了。于是,微软更进一步,把界面描述语言又向设计师方向推进了一层,也就是XAML语言。于是,开发和设计的格局就变成了这样:
    有了XAML和将XAML解析为C#/VB的解析器,设计师们就能以自己最高的工作效率与程序员们合作开发软件了。目前关于XAML是如何解析成C#/VB的资料非常少。
    Name揭秘
    下面让我们把目光集中在XAML->C#的解析上来,看看Name和x:Name的本质是什么。
    让我们看一段代码:
    <Window x:Class="WpfApplication2.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="100" Width="300" Background="SteelBlue"> <StackPanel> <TextBox Name="textBox1"/> <TextBox Name="textBox2"/> <Button Content="Show Name" Click="Button_Click"/> </StackPanel>
    <x:Code> <![CDATA[
    private void Button_Click(object sender, RoutedEventArgs e) { Button btn = e.OriginalSource as Button; textBox1.Text = btn.Name;
    textBox2.Name = "Made_in_China"; textBox2.Text = textBox2.Name; }
    ]]> </x:Code> </Window>
    运行结果是:
    我用XAML定义了三个UI元素,其中两个TextBox是有Name的。凡是你在XAML代码里设置了它的Name,那么在C#代码里就会有一个对应的变量。这可也很好解释,看看IL程序集就知道了——
    不难看出,XAML解析器会为XAML代码中设置了Name的元素声明同名的引用变量,而且设置Name的元素则不会有引用变量生成(不过这个元素对应的对象是存在的,并且是VisualTree/LogicalTree上的结点)。
    通过上面的代码,我看可以看出,Name的作用有两个:
    1. 告诉XAML解析器为设置了Name的元素声明对应的引用变量(本例中是textBox1和textBox2),变量名使用Name的值。
    2. 将XAML元素对应的对象(本例中是两个TextBox的实例)的Name属性设置为Name的值。
    注意,引用变量一旦声明之后名字就不能改了,但对象的Name属性仍然可以改(示例中我就把由textBox2变量引用着的实例的Name属性改成Made_in_China了。)
    让我们再挖深点儿——TextBox的Name属性是从哪儿继承来的呢?查一查MSDN,原来是从FrameworkElement那儿继承来的。这个Name属性是非常重要的——如果你想在一棵“树”上查找叫某个名字的元素,调用“树根”的FindName方法就可以做到了。特别需要注意的是——FindName所使用的参数是对象Name属性的值而不是引用着这个对象的变量的名字。如果你的程序里只在XAML里设置了一次Name,那么引用变量的名字和对象Name属性的值恰好一样。但如果你改变了对象Name属性的值,那可就要小心了!请看下面的代码:
    <Window x:Class="WpfApplication2.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="100" Width="300" Background="SteelBlue"> <StackPanel> <TextBox Name="textBox1"/> <TextBox Name="textBox2"/> <Button Content="Show Name" Click="Button_Click"/> </StackPanel>
    <x:Code> <![CDATA[
    private void Button_Click(object sender, RoutedEventArgs e) 

    x:Name 唯一地标识 XAML 定义的对象,以便于从代码隐藏或通用代码中访问对象图中实例化的对象。x:Name 一旦应用于支持编程模型,便可被视为与由构造函数返回的用于保存对象引用或实例的变量等效。
      x:Name 用来在XAML中表示一个指定对象的名称;可以通过他来访问XAML对应隐藏代码所关联的对象。
      Name 许多框架的类中都有Name这个属性,而在WPF中,x:Name和Name是可以互换的。
      所以现阶段他们两者做的是同样的工作。
    
      结果:
      1. xmal中,永远只有一个, 它就是x:Name;
      2. 我们在xaml中有时能使用的Name,其实是被映射到x:Name上的。
    
      原因:
      1. 所有的Type在xaml中都能使用x:Name,即使这个type 没有定义一个叫着Name的Property。因为xmal会在后台为其分配一个field来存储,以便在Binding等里面使用。
      2. 像FrameworkElement, VisualStateGroup的某些type,我们在xaml中可以使用Name来代替x:Name,因为它们定义了Name Property,但是最关键的是在type上声明了一个Attribute,[RuntimeNameProperty("Name")],正是这个 attribute把Name映射到了x:Name上,所以让Name可以做到x:Name的功能。
    
      扩展:
      如果我们的某些type需要定义一个 Property,并且想做到x:Name的能力,别忘了加上RuntimeNamePropertyAttribute!
      这个只是一个代码编写风格和习惯的问题,而不是一个技术问题。s
  • 相关阅读:
    021.day21 反射 Class类 反射常用操作
    020.day20 线程概述 多线程优缺点 线程的创建 线程常用方法 生命周期 多线程同步
    019.day19 缓冲流 对象流 标准输入输出流
    018.day18 map集合如何实现排序 File类 IO流 字节流 字符流 编码
    017.day17 Map接口 克隆 treeSet集合排重缺陷
    016.day16 HashSet TreeSet 比较器Comparable Comparator
    015.day15
    014.day14
    013.day13
    线程
  • 原文地址:https://www.cnblogs.com/mxxblog/p/2364793.html
Copyright © 2011-2022 走看看