x:Name的作用有两个:
(1)告诉XAML编译器,当一个标签带有x:Name时除了为这个标签生成对应实例外还要为这个实例声明一个引用变量,变量名就是x:Name的值。
(2)将XAML标签所对应对象的Name属性(如果有)也设为 x: Name的值,并把这个值注册到UI树上,以方便查找。
先说结论:
- XAML中x:Name与Name并不完全等价。
- 不是所有类型都可以使用Name,但是任何类型都可以使用x:Name。
- 只有拥有Name属性,才可以在XAML中使用Name。不同于x:Name,因为这个是附加属性。
- 并且该类型、或者其父类型标记了RuntimeNameProperty特性,才拥有与x:Name一样的效果。
我们先把下面这个代码用IL反编译器打开,你会发现 Window类里不包含任何字段。
然后为< textbox>标签添加x:Name:
private void Button_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(textBox.Name))
{
textBox.Text = "No name!";
}
else
{
textBox.Text = textBox.Name;
}
}
因为 Textbox的实例由名为 textBox的引用变量所引用,所以我们可以通过引用变量直接访问实例。
单击按钮后, Textbox中出现“ textBox”,说明x:Name不但让编译器声明了引用变量,同时还为实例的Name属性赋了值。使用IL反编译器查看编译结果,你能在 Window类中找到 textBox这个字段。注意,如果一个标签对应的实例没有Name这个属性,那么 X: Name作用就只剩下为这个实例创建引用变量了。
经常会有初学者问:在XAML代码中是应该使用Name呢,还是x:Name? Name属性定义在FrameworkElement类中,这个类是WPF控件的基类,所以所有WPF控件都具有Name这个属性。当一个元素具有Name属性时,你使用Name或x:Name效果是一样的。比如< Button x:Name="btn"和< Button Name=“btn”>,XAML编译器的动作都是声明名为btn的Button类型变量并引用一个Button类型实例,而且此实例的Name属性值亦为btn。此时,Name和x:Name是可以互换的,只是不能同时出现在一个元素中。对于那些没有Name属性的元素,为了在XAML声明时也创建引用变量以便在C#代码中访问,我们就只能使用x:Name。因为x:Name的功能涵盖了Name属性的功能,所以全部使用x:Name以增强代码的统一性和可读性。
- 所有的Type在XAML中都能使用x:Name,即使这个type 没有定义一个叫着Name的Property。因为XAML会在后台为其分配一个field来存储,以便在Binding等里面使用。
- 像FrameworkElement, VisualStateGroup的某些type,我们在XAML中可以使用Name来代替x:Name,因为它们定义了Name Property,但是最关键的是在type上声明了一个Attribute,[RuntimeNameProperty(“Name”)],正是这个Attribute把Name映射到了x:Name上,所以让Name可以做到x:Name的功能。



