在WPF中,x:Name和Name属性之间有什么区别?


573

标题说明了一切。有时,Namex:Name属性可以互换。

那么,它们之间的明确区别是什么?何时使用一种优于另一种呢?

以错误的方式使用它们是否会对性能或内存产生影响?


响应表明,x:Name始终使用时间是可以的。我只需要将其更改为Name否则,就无法在我的.xaml.cs代码中引用该控件,因此我将假定不再总是可以正常工作了。
Ortund

1
关于回滚,Drew所说的“标题说明了一切”又赋予了什么额外的含义?这不是多余的吗?(我之所以进行编辑,是因为我倾向于不鼓励使用对话式的填充语-这比“我想知道您是否可以帮助我”更有意义。)
Halfer

Answers:


481

XAML中实际上只有一个名称,即x:Name。诸如WPF之类的框架可以选择x:Name使用RuntimeNamePropertyAttribute其类上的on(将类属性之一指定为映射到XAML的x:Name属性)来将其属性映射到XAML。

这样做的原因是为了允许在运行时已经具有“名称”概念的框架,例如WPF。例如,在WPF中,FrameworkElement引入了Name属性。

通常,一个类不需要存储名称x:Name即可使用。x:NameXAML的所有方法都是生成一个字段,以将值存储在类后面的代码中。运行时对该映射进行的操作取决于框架。

那么,为什么有两种方法可以做同一件事?简单的答案是因为有两个概念映射到一个属性。WPF希望在运行时保留一个元素的名称(可通过Bind等使用),而XAML需要知道您希望通过类后面代码中的字段访问哪些元素。WPF通过将Name属性标记为x:Name的别名来将这两者联系在一起。

将来,XAML将更多地用于x:Name,例如允许您通过按名称引用其他对象来设置属性,但在3.5及更低版本中,它仅用于创建字段。

您是否应该使用一个还是另一个确实是样式问题,而不是技术问题。我将其留给他人以提出建议。

另请参见AutomationProperties.Name与VS x:Name,辅助功能工具和某些测试工具使用AutomationProperties.Name。


2
在Visual Studio 2010中,通过设计器编辑XAML时,将设置Name属性(不是x:Name)。似乎MS鼓励在x:Name之上使用Name,所以我想这是事实上的标准。
星云

11
我不认为两者通常是可以互换的。命名用户控件是必需的,x:Name因为Name不会创建在代码隐​​藏中识别的字段。不过,我仍然不知道为什么会这样。
Libor

5
他们不是,我不是说暗示他们做到了。在WPF中,如果元素具有Name属性,则它们含义相同。如果元素没有Name属性,则必须使用x:Name
chuckj

90

它们不是同一件事。

x:Name是xaml概念,主要用于参考元素。当给元素提供x:Name xaml属性时,“指定x:Name的名称将成为在处理xaml时在基础代码中创建的字段的名称,并且该字段包含对该对象的引用。” (MSDN)因此,这是一个设计师生成的字段,默认情况下具有内部访问权限。

Name是a的现有字符串属性FrameworkElement,以xaml属性的形式与任何其他wpf元素属性一起列出。

因此,这也意味着x:Name可以在更广泛的对象上使用。这是一种使xaml中的任何内容都能被给定名称引用的技术。


6
那么,为什么可以将Name或x:Name与Binding.ElementName一起使用?似乎x:Name属性不仅用于在生成的代码中命名字段,而且在运行时还可以在元数据中使用。
德鲁·诺阿克斯

它是一个生成的字段,类似于WinForms编辑器的“设计”属性中的“名称”字段。您在此处在属性列表中放置了一个名称,该名称即成为字段的名称。这是相同的行为。当然,它是在运行时提供的,因为它是一个内部字段,被编译为后面的代码。Binding.ElementName检查是否存在两种情况,即xaml编辑器“魔术”,x:Name本身并不是魔术。
Kenan EK,2009年

39

x:Name和Name引用不同的名称空间。

x:name是对Xaml文件顶部默认定义的x名称空间的引用。

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

只是说Name使用下面的默认名称空间。

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

x:Name表示使用具有x别名的名称空间。x是默认值,大多数人都保留它,但是您可以将其更改为任意值

xmlns:foo="http://schemas.microsoft.com/winfx/2006/xaml"

所以您的参考将是foo:name

在WPF中定义和使用命名空间


OK,让我们以另一种方式来看待。假设您将一个按钮拖放到Xaml页面上。您可以通过x:namename这两种方式来引用。所有xmlns =“ http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x =“ http://schemas.microsoft.com/winfx/2006/xaml”都是对多个命名空间的引用。由于xaml拥有Control命名空间(不是100%),而表示形式拥有FrameworkElement,而Button类的继承模式为:

Button : ButtonBase
ButtonBase : ContentControl, ICommandSource
ContentControl : Control, IAddChild
Control : FrameworkElement
FrameworkElement : UIElement, IFrameworkInputElement, 
                    IInputElement, ISupportInitialize, IHaveResources

因此,正如人们期望的那样,任何继承自FrameworkElement的东西都将有权访问其所有公共属性。因此,对于Button,它是从FrameworkElement的层次结构树的顶部获取其Name属性。 因此,您可以说x:NameName,它们都将从FrameworkElement中访问getter / setter。

MSDN参考

WPF定义XAML处理器使用的CLR属性,以将多个CLR名称空间映射到单个XML名称空间。所述XmlnsDefinitionAttribute属性被放置在产生该组件的源代码的程序集的水平。WPF程序集源代码使用此属性将各种常见的命名空间(例如System.Windows和System.Windows.Controls)映射到http://schemas.microsoft.com/winfx/2006/xaml/presentation命名空间。

因此,程序集属性将类似于:

PresentationFramework.dll-XmlnsDefinitionAttribute:

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Data")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Navigation")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Shapes")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Documents")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Controls")]  

1
我认为它成立并不http://schemas.microsoft.com/winfx/2006/xaml成立,Control因为您可以直接在XAML中使用它而无需使用“ x”名称空间:<Control />
Drew Noakes

23

它们都是同一回事,很多框架元素本身都公开了name属性,但对于那些不包含它们的人,您可以使用x:name-我通常只坚持使用x:name,因为它适用于所有情况。

控件可以根据需要将名称本身公开为依赖项属性(因为它们需要在内部使用该依赖项属性),也可以选择不使用。

在MSDN更多细节在这里这里

一些WPF框架级应用程序可能能够避免使用x:Name属性,因为在WPF命名空间中为几个重要基类(例如FrameworkElement / FrameworkContentElement)指定的Name依赖项属性满足了相同的目的。仍然存在一些常见的XAML和框架方案,其中需要对不具有Name属性的元素进行代码访问,尤其是在某些动画和情节提要支持类中。例如,如果要从代码中引用x:Name,则应在XAML中创建的时间轴和转换上指定它们。

如果Name可以作为类的属性使用,则Name和x:Name可以作为属性互换使用,但是如果在同一个元素上同时指定两者,则会导致错误。


4
如果没有区别,那么为什么会有两种方式做同一件事?这两种方式都存在于WPF的第一版中。
Drew Noakes

@Steve,尽管到目前为止,没有一个答案非常合适,但我没有对这个问题给出任何答案。
Drew Noakes

我不认为答案不仅会给您答案,还会给您链接到MSDN以获得有关该主题的更多信息不合适吗?:-)
史蒂文·罗宾斯

5
@Steve您的原始答案未解决我的问题,因此未发表评论。我不是在寻找盲目的“这样做”,而是一个有见地的答案,它解释了为什么存在两种方法,即使其中一种方法一直有效。技术上正确!=适当。您的更新要好得多。
Drew Noakes

1
此处的答案大致相同:wpfwiki.com/WPF%20Q16.4.ashx x:Name为控件提供了在隐藏代码中使用的名称。某些类将出于相同目的提供名称属性。对于这些类,x:name和name之间没有区别。
Vegar

11

如果您有自定义控件,则X:Name可能会导致内存问题。它将为NameScope条目保留一个存储位置。

我说除非必要,否则不要使用x:Name。


同意 在一个信息亭应用程序上工作,该应用程序存在大量内存泄漏,而先前的开发团队的解决方案只是强制重启。许多泄漏很容易识别。但是,在修复了通过IntelliTrace和JustTrace找到的那些之后,一些引用仍然无法进行隐式和显式垃圾回收。我读到:support.scichart.com/index.php?/News/NewsItem/View/21/… 发现减少x:Name可以进一步提高性能。
MachinusX 2014年

2
这是我的理解这会影响这两个 名称X:名称为都被添加到名称范围。如果您的元素上需要一个名称,那就无所不用其极了。您可以通过来对没有名称的元素进行代码复制FrameworkElement.RegisterName("elementname")。但是,如果您调用FrameworkElement.UnregisterName("elementname")它,则可以“取消引用”。
亚当·卡维尼斯

8

名称

  1. 只能用于FrameworkElement和FrameworkContentElement的后代;
  2. 可以通过SetValue()和类似属性的代码在后台进行设置。

x:名称

  1. 几乎可以用于所有XAML元素;
  2. 不能通过SetValue()从后台代码设置;因为它是指令,所以只能在对象上使用属性语法进行设置。

在XAML中为一个FrameworkElement或FrameworkContentElement使用两个指令将导致异常:如果XAML是标记编译的,则该异常将在标记编译时发生,否则将在加载时发生。


7

唯一的区别是,如果将用户控件用于Same Assembly中的控件,则Name将无法标识您的控件,并且会出现错误“在同一Assembly中为控件使用x:Name”。因此x:Name是WPF中命名控件的WPF版本。名称仅用作Winform Legacy。他们希望区分WPF和Winforms中控件的命名,因为他们使用Xaml中的属性来从其他使用x:表示控件名称的程序集中识别控件。

请记住,不要仅仅为了保留控件的名称而将其命名,因为它作为空白驻留在内存中,它会警告您名称已用于控件,但从未使用过。


7

x:Name 意思是:在后面的代码中创建一个字段来保存对该对象的引用。

Name 表示:设置此对象的name属性。


这不是真的。它们都可以从后面的代码中访问,但是有趣的是,只有x:Name可以在运行时更新。坚果

4

我总是使用x:Name变体。我不知道这是否会影响性能,我只是因为以下原因才发现它更容易。如果您自己的用户控件驻留在另一个程序集中,则“名称”属性并不总是足够的。这使得粘贴x:Name属性也更加容易。


4
如果没有区别,那么为什么会有两种方式做同一件事?这两种方式都存在于WPF的第一版中。
Drew Noakes

3

它不是WPF项,而是标准XML,BtBh正确回答了该问题,x表示默认名称空间。在XML中,当您不为元素/属性添加名称空间前缀时,它会假定您需要默认名称空间。所以打字只是Name空手而已x:Name。有关XML名称空间的更多详细信息,请参见链接文本。


诱惑到-1 x:表示不同的XML名称空间,这是正确的,但这实际上并不是对Q的有用答案,Q是关于何时需要不使用另一个。:/
Tim Lovell-Smith

2

答案之一是x:name将在不同的程序语言(例如c#)中使用,而name将用于框架。老实说,这就是我的感觉。


2

指定的x:Name成为处理XAML时在基础代码中创建的字段的名称,并且该字段包含对该对象的引用。在Silverlight中,使用托管API,创建此字段的过程由MSBuild目标步骤执行,这些步骤还负责将XAML文件及其代码隐藏的部分类连接在一起。此行为不一定是指定的XAML语言。Silverlight适用于在其编程和应用程序模型中使用x:Name的特定实现。

阅读有关MSDN的更多信息...


2

当您在XAML中声明Button元素时,您所引用的是Windows运行时中定义的类Button。

按钮具有许多属性,例如背景,文本,边距,.....和一个名为名称的属性。

现在,当您在XAML中声明一个Button时,就像创建一个匿名对象,碰巧它具有一个名为Name的属性。

通常,您不能引用匿名对象,但是在WPF框架中,XAML处理器使您可以通过对Name属性指定的任何值来引用该对象。

到目前为止,一切都很好。

创建对象的另一种方法是创建一个命名对象而不是匿名对象。在这种情况下,您可以设置XAML命名空间,该属性可以被称为Name的对象(并且由于它在XAML命名空间中,因此具有X :),因此可以标识您的对象并对其进行引用。

结论:

名称是特定对象的属性,但是X:Name是该对象的一个​​属性(有一个定义通用对象的类)。


0

我的研究是x:Name作为全局变量。但是,Name作为局部变量。这是否意味着x:Name可以在XAML文件中的任何位置调用它,但Name不能。
例:

<StackPanel>
<TextBlock Text="{Binding Path=Content, ElementName=btn}" />
<Button Content="Example" Name="btn" />
</StackPanel>
<TextBlock Text="{Binding Path=Content, ElementName=btn}" />

您不能将Name Binding属性Content设置Button为“ btn”,因为它位于外部StackPanel

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.