Name
和x:Name
属性是可互换的。它们之间的确定性区别是什么?何时最好使用一个而不是另一个?
以错误的方式使用它们是否会对性能或内存产生影响?
#1 楼
在XAML中,实际上只有一个名称x:Name
。诸如WPF之类的框架可以选择使用其类上的x:Name
将其属性之一映射到XAML的RuntimeNamePropertyAttribute
,该类将其中一个类属性指定为映射到XAML的x:Name属性。这样做的原因是允许运行时已经具有“名称”概念的框架,例如WPF。例如,在WPF中,
FrameworkElement
引入了Name属性。通常,一个类不需要存储该名称即可使用
x:Name
。对XAML的所有x:Name
手段都是生成一个字段以将值存储在类后面的代码中。运行时对该映射的作用取决于框架。那么,为什么有两种方法可以完成同一件事?简单的答案是因为有两个概念映射到一个属性。 WPF希望在运行时保留一个元素的名称(可通过Bind等使用),而XAML需要知道您希望通过类后面代码中的字段访问哪些元素。 WPF通过将Name属性标记为x:Name的别名来将这两者联系在一起。
以后,XAML将对x:Name有更多用途,例如允许您通过引用来设置属性其他对象按名称命名,但在3.5及更低版本中,它仅用于创建字段。
您是否应该使用一个或另一个确实是样式问题,而不是技术问题。我将其留给他人以提出建议。
另请参见AutomationProperties.Name VS x:Name,AutomationProperties.Name由辅助功能工具和某些测试工具使用。
评论
在Visual Studio 2010中,当通过设计器编辑XAML时,将设置Name属性(不是x:Name)。似乎MS鼓励使用Name而不是x:Name,所以我想这是事实上的标准。
–星云
13年2月27日在9:15
我不认为两者通常是可以互换的。命名用户控件需要x:Name,因为Name不会创建在代码隐藏中识别的字段。我仍然不知道为什么会这样。
– Libor
13年7月13日在8:40
他们不是,我不是说暗示他们做到了。在WPF中,如果元素具有Name属性,则它们含义相同。如果该元素没有Name属性,则必须使用x:Name。
– chuckj
13年7月27日在0:41
@Libor今天,对于从FrameworkElement派生的任何类型使用Name还是x:Name都绝对没有区别(它包括您将在XAML中使用的大多数类型(包括UserControl),无论如何都将正确生成成员)。这是因为FrameworkElement用[RuntimeNameProperty(“ Name”)]装饰。
– bitbonk
6月14日7:34
#2 楼
它们不是一回事。x:Name
是xaml概念,主要用于引用元素。当为元素赋予x:Name xaml属性时,“指定的x:Name
成为在处理xaml时在基础代码中创建的字段的名称,并且该字段包含对该对象的引用。” (MSDN)因此,这是一个由设计人员生成的字段,默认情况下具有内部访问权限。Name
是FrameworkElement
的现有字符串属性,与任何其他wpf元素属性一样以xaml的形式列出属性。因此,这也意味着x:Name
可以用于更广泛的对象。这是一种使xaml中的任何内容都能被给定名称引用的技术。评论
那么,为什么可以将Name或x:Name与Binding.ElementName一起使用?似乎x:Name属性不仅用于在生成的代码中命名字段,而且在运行时还可以在元数据中使用。
–德鲁·诺克斯(Drew Noakes)
09年7月15日在9:21
它是一个生成的字段,类似于WinForms编辑器的“设计”属性中的“名称”字段。您在此处在属性列表中放置了一个名称,该名称即成为字段的名称。这是相同的行为。当然,它是在运行时提供的,因为它是一个内部字段,被编译为后面的代码。 Binding.ElementName检查是否存在两种情况,即xaml编辑器“魔术”,x:Name本身并不是魔术。
– Kenan E. K.
09年7月15日在12:00
无论使用x:Name还是Name,都将生成一个字段。对于从FrameworkElement派生的所有类型(您在XAML中使用的大多数类型都是),所有类型的x:Name和Name都没有区别,只有一个例外:如果要给UserControl一个名称,并且UserControl在同一声明中还需要在其中使用程序集的地方,必须使用x:Name,因为XAML解析器受到限制。
– bitbonk
6月14日11:05
#3 楼
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:名称是使用具有x别名的名称空间。 x是默认值,大多数人都保留它,但是您可以将其更改为任意值
xmlns:foo="http://schemas.microsoft.com/winfx/2006/xaml"
,因此您的引用将是foo:name
在WPF中定义和使用命名空间
OK,让我们以另一种方式来看待。假设您将一个按钮拖放到Xaml页面上。您可以通过x:name和name引用这两种方式。所有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:Name或Name,它们都将从FrameworkElement中访问getter / setter。 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")]
评论
我认为http://schemas.microsoft.com/winfx/2006/xaml拥有Control是不正确的,因为您可以直接在XAML中使用它而无需使用'x'命名空间:
–德鲁·诺克斯(Drew Noakes)
09年10月1日在15:22
#4 楼
它们都是同一回事,很多框架元素本身都公开了name属性,但是对于那些不包含它们的人,您可以使用x:name-我通常只坚持使用x:name,因为它适用于所有内容。如果愿意,控件可以将名称本身公开为依赖项属性(因为它们需要在内部使用该依赖项属性),也可以选择不这样做。
此处的msdn中的更多详细信息:
一些WPF框架级别的应用程序
可以避免使用
x:Name属性,因为WPF名称空间中指定的Name
依赖属性
满足了几个重要基类的
,例如
FrameworkElement / FrameworkContentElement
同样的目的在
仍存在一些常见的XAML和框架
场景,其中需要对没有Name属性的
元素进行代码访问
,尤其是在某些
动画和情节提要支持中
类。例如,如果您
打算从代码中引用它们,则应
在时间轴上指定x:Name并在XAML中创建的转换指定
。
如果Name可用作为
类的属性,名称和x:Name可以互换使用
作为属性,但是如果在同一元素上同时指定
,则会导致
错误。 br />
评论
如果没有区别,那么为什么会有两种方法来做同一件事?这两种方式都存在于WPF的第一版中。
–德鲁·诺克斯(Drew Noakes)
09年2月26日在11:15
@Steve,尽管到目前为止,没有一个答案非常合适,但我没有对这个问题给出任何答案。
–德鲁·诺克斯(Drew Noakes)
09年2月26日在11:53
我不认为答案不仅会给您答案,还会给您链接到MSDN以获得有关该主题的更多信息不合适吗? :-)
–史蒂文·罗宾斯(Steven Robbins)
09-2-26在11:55
@Steve您的原始答案未解决我的问题,因此未发表评论。我不是在寻找盲目的“这样做”,而是一个有见地的答案,它解释了为什么存在两种方法,即使其中一种方法一直有效。技术上正确!=适当。您的更新要好得多。
–德鲁·诺克斯(Drew Noakes)
09年2月26日在15:16
此处的答案大致相同:wpfwiki.com/WPF%20Q16.4.ashx x:Name为控件提供了在代码隐藏中使用的名称。某些类将出于相同目的提供名称属性。对于这些类,x:name和name之间没有区别。
–素食主义者
09年2月26日在23:57
#5 楼
如果您有自定义控件,则X:Name可能会导致内存问题。它将为NameScope条目保留一个存储位置。除非必要,否则我说永远不要使用x:Name。
评论
同意在一个有大量内存泄漏的信息亭应用程序上工作,而先前的开发团队的解决方案只是强制重启。许多泄漏很容易识别。但是,在修复了通过IntelliTrace和JustTrace找到的内容之后,一些引用仍然无法进行隐式和显式垃圾回收。我读到:support.scichart.com/index.php?/News/NewsItem/View/21/…发现减少x:Name进一步提高了性能。
– MachinusX
2014年8月20日在3:40
据我了解,这会影响Name和x:Name,因为它们都被添加到NameScope中。如果您需要在元素上使用名称,则无需解决。您可以通过FrameworkElement.RegisterName(“ elementname”)在没有名称的元素上复制代码。但是,如果调用FrameworkElement.UnregisterName(“ elementname”),则可以将其“取消引用”。
–亚当·卡夫尼斯(Adam Caviness)
17年4月27日在12:47
#6 楼
名称:只能用于FrameworkElement和FrameworkContentElement的后代;可以通过SetValue()和类似属性的代码在后台设置。
x:Name:
几乎可以用于所有XAML元素;
不能通过SetValue()从
代码隐藏设置;只能在对象上使用属性
语法来设置它,因为它是一个指令。
在XAML中将两个指令同时用于一个FrameworkElement或FrameworkContentElement会导致异常:如果XAML是标记编译的,该异常将在标记编译时发生,否则将在加载时发生。
#7 楼
唯一的区别是,如果将用户控件用于Same Assembly中的控件,则Name将无法标识您的控件,并且会出现错误“在同一Assembly中为控件使用x:Name”。因此x:Name是WPF中命名控件的WPF版本。名称仅用作Winform Legacy。他们想区分WPF和Winforms中控件的命名,因为他们使用Xaml中的属性从使用x:作为控件名称的其他程序集中识别控件。
请记住,不要为控件添加名称,只是为了保留它而已,因为它作为空白驻留在内存中,它会警告您名称已被用于控件,但是它从未使用过。
#8 楼
x:Name
表示:在后面的代码中创建一个字段来保存对该对象的引用。Name
表示:设置此对象的name属性。评论
这不是真的。它们都可以从后面的代码中访问,但是有趣的是,只有x:Name可以在运行时更新。坚果
–user1228
17-10-4在12:43
#9 楼
我总是使用x:Name变体。我不知道这是否会影响性能,但由于以下原因,我发现它更容易。
如果您有自己的用户控件位于另一个程序集中,则只是“名称”属性并不总是足够的。这使得粘贴x:Name属性变得更加容易。
评论
如果没有区别,那么为什么会有两种方法来做同一件事?这两种方式都存在于WPF的第一版中。
–德鲁·诺克斯(Drew Noakes)
09年2月26日在11:13
#10 楼
这不是WPF项,而是标准XML项,BtBh正确回答了该问题,x表示默认名称空间。在XML中,当您不为元素/属性添加名称空间前缀时,它会假定您要使用默认名称空间。因此,仅键入
Name
只是x:Name
的简写形式。有关XML名称空间的更多详细信息,请参见链接文本评论
诱惑为-1 x:表示不同的XML名称空间,这是正确的,但这实际上不是对Q的有用答案,Q是关于何时需要不使用另一个。 :/
–蒂姆·洛弗尔·史密斯(Tim Lovell-Smith)
2010年1月18日15:50
#11 楼
当处理XAML时,指定的x:Name成为在基础代码中创建的字段的名称,并且该字段包含对该对象的引用。在Silverlight中,使用托管API,创建此字段的过程由MSBuild目标步骤执行,这些步骤还负责将XAML文件及其代码隐藏的部分类连接在一起。此行为不一定是指定的XAML语言。这是Silverlight应用于在其编程和应用程序模型中使用x:Name的特定实现。有关MSDN的更多信息...
#12 楼
当您在XAML中声明Button元素时,您引用的是Windows运行时中定义的类Button。Button具有许多属性,例如背景,文本,边距,...和一个属性
现在,当您在XAML中声明一个Button时,就像创建一个匿名对象,碰巧具有一个名为Name的属性。
通常,您不能引用匿名对象,但是在WPF框架中,XAML处理器使您可以通过为Name属性赋予任何值来引用该对象。到目前为止,一切都很好。
另一种方法创建对象就是创建一个命名对象而不是匿名对象。在这种情况下,您可以设置XAML命名空间具有一个名为Name的对象的属性(由于它在XAML命名空间中,因此具有X :),因此可以标识您的对象并对其进行引用。
结论:
名称是特定对象的属性,但是X:Name是该对象的一个属性(有一个类定义了常规对象)。
#13 楼
答案之一是x:name将在不同的程序语言(例如c#)中使用,而name将用于框架。老实说,这就是我的感觉。#14 楼
也可以使用带有内部文本的属性元素语法来设置Name
,但这并不常见。相反,不能以x:Name
属性元素语法或使用XAML
的代码设置SetValue
;它只能在对象上使用属性语法设置,因为它是指令。如果
Name
可以作为类的属性使用,则Name
和x:Name
可以互换用作属性,但是解析异常将如果两个都在同一个元素上指定,则返回结果。如果XAML是标记编译的,则异常将在标记编译时发生,否则将在加载时发生。#15 楼
我的研究是将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}" />
您不能
Binding
属性Content
具有名称的Button
中的一个为“ btn”,因为它位于StackPanel
之外
评论
响应表明,始终使用x:Name可以正常工作。我只需要将其更改为Name即可,否则我无法在.xaml.cs代码中引用该控件,因此我将假定不再总是可以正常工作了。关于回滚,Drew所说的“标题说明了一切”又赋予了什么额外的含义?这不是多余的吗? (我之所以进行编辑,是因为我倾向于不鼓励使用对话式填充语-这比“我想知道您是否能帮助我”更有意义。)