ChatGPT解决这个技术问题 Extra ChatGPT

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

有时,Namex:Name 属性似乎可以互换。

那么,它们之间的明确区别是什么,什么时候最好使用一种而不是另一种呢?

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

响应表明始终使用 x:Name 可以正常工作。我只需要将它更改为 Name 否则我无法在我的 .xaml.cs 代码中引用该控件,因此我将假设它不再是一直正常工作的情况。

R
Robert Harvey

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

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

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

那么,为什么有两种方法可以做同样的事情呢?简单的答案是因为有两个概念映射到一个属性。 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 所以我猜这是事实上的标准。
我不认为这两者通常可以互换。命名用户控件需要 x:Name,因为 Name 不会创建要在代码隐藏中识别的字段。不过,我仍然不知道为什么会发生这种情况。
他们不是,我也不是要暗示他们做到了。在 WPF 中,如果元素具有 Name 属性,则它们的含义相同。如果元素没有 Name 属性,则必须使用 x:Name
@Libor 今天,对于从 FrameworkElement 派生的任何类型(包括您在 XAML 中使用的大多数类型包括 UserControl,一个成员在任何情况下都会正确生成)。这是因为 FrameworkElement 是用 [RuntimeNameProperty("Name")] 装饰的。
K
Kenan E. K.

它们不是同一件事。

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

NameFrameworkElement 的现有字符串属性,以 xaml 属性的形式作为任何其他 wpf 元素属性列出。

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


那么为什么 Name 或 x:Name 可以与 Binding.ElementName 一起使用呢?似乎 x:Name 属性不仅用于在生成的代码中命名字段,而且在运行时在元数据中也可用。
它是一个生成的字段,类似于 WinForms 编辑器的设计属性中的字段名称。在那里,您在属性列表中放置一个名称,它成为一个字段的名称。这是相同的行为。当然,它在运行时可用,因为它是编译到后面代码中的内部字段。 Binding.ElementName 检查任何一种情况,即 xaml 编辑器“神奇”,x:Name 本身并不神奇。
无论您使用 x:Name 还是 Name,都会生成一个字段。对于从 FrameworkElement 派生的所有类型(您在 XAML 中使用的大多数类型都是),x:Name 和 Name 之间没有区别,只有一个例外:如果您想给 UserControl 一个名称 和 UserControl在您还想使用它的同一程序集中声明您必须使用 x:Name 因为 XAML 解析器的限制。
R
Robert Harvey

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

Define and Use Namespaces in WPF

好的,让我们换一种方式来看。假设您将一个按钮拖放到您的 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。

MSDN Reference

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”命名空间:<Control />
R
Robert Harvey

它们都是一样的,很多框架元素自己都暴露了一个 name 属性,但对于那些不这样做的人,你可以使用 x:name - 我通常只坚持使用 x:name 因为它适用于所有东西。

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

msdn herehere 中的更多详细信息:

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


如果没有区别,那么为什么会有两种方法来做同样的事情呢?这两种方式都存在于 WPF 的第一个版本中。
@Steve,我没有对这个问题的任何答案投反对票,尽管到目前为止它们都不是非常合适的。
我看不出一个不仅可以为您提供答案,而且还可以为您提供指向 MSDN 以获取有关该主题的更多信息的链接的答案是不合适的吗? :-)
@Steve您的原始答案没有解决我的问题,因此我发表了评论。我不是在寻找盲目的“这样做”,而是一个有见地的答案,它解释了为什么存在两种方式,即使其中一种方式一直有效。技术上正确!=适当。你的更新好多了。
这里的答案大致相同:wpfwiki.com/WPF%20Q16.4.ashx x:Name 为控件提供了一个名称,以便在代码隐藏中使用。某些类将提供名称属性用于相同目的。对于这些类,x:name 和 name 没有区别。
s
scott

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

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


同意。在一个有大量内存泄漏的信息亭应用程序上工作,而之前的开发团队的解决方案只是强制重启。许多泄漏很容易识别。然而,在修复了通过 IntelliTrace 和 JustTrace 找到的那些之后,一些 refs 仍然避开了隐式和显式垃圾收集。我读到:support.scichart.com/index.php?/News/NewsItem/View/21/… 发现减少 x:Name 进一步提高了性能。
据我了解,这会影响 both Namex:Name 因为两者都已添加到 NameScope。如果您的元素需要名称,则无法绕过它。您可以通过 FrameworkElement.RegisterName("elementname") 在没有名称的元素上复制代码。但是,如果您调用 FrameworkElement.UnregisterName("elementname"),它可以被“取消引用”。
O
Oleksandr Zolotarov

姓名:

只能用于 FrameworkElement 和 FrameworkContentElement 的后代;可以通过 SetValue() 和类似属性的代码隐藏设置。

x:姓名:

可用于几乎所有 XAML 元素;不能通过 SetValue() 从代码隐藏设置;它只能使用对象的属性语法来设置,因为它是一个指令。

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


B
Bipul Kumar

唯一的区别是,如果您将用户控件用于同一程序集中的控件,则名称将无法识别您的控件,并且您将收到错误“使用 x:Name 用于同一程序集中的控件”。所以 x:Name 是 WPF 中命名控件的 WPF 版本。名称仅用作 Winform Legacy。他们想要区分 WPF 和 winforms 中控件的命名,因为他们使用 Xaml 中的属性来识别来自其他程序集的控件,他们使用 x: 表示控件名称。

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


i
itzmebibin

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

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


这并不完全正确。它们都可以从代码隐藏中访问,但有趣的是,只有 x:Name 可以在运行时更新。坚果。
S
Simon

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


如果没有区别,那么为什么会有两种方法来做同样的事情呢?这两种方式都存在于 WPF 的第一个版本中。
C
Community

它不是 WPF 项,而是标准 XML 项,BtBh 已正确回答,x 指的是默认命名空间。在 XML 中,当您不使用命名空间作为元素/属性的前缀时,它假定您需要默认命名空间。所以只输入 Name 只不过是 x:Name 的简写。有关 XML 命名空间的更多详细信息,请参阅 link text


诱惑到 -1 x: 指的是不同的 XML 命名空间,没错,但这实际上并不是对 Q 的有用答案,即你什么时候需要使用一个而不是另一个。 :/
E
Edd

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

Read More on MSDN...


L
LJNielsenDk

当您在 XAML 中声明 Button 元素时,您指的是在 Windows 运行时中定义的称为 Button 的类。

Button 有许多属性,例如背景、文本、边距、......以及一个名为 Name 的属性。

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

通常,您不能引用匿名对象,但在 WPF 框架中,XAML 处理器允许您通过为 Name 属性提供的任何值来引用该对象。

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

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

结论:

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


d
daddycardona

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


A
Ali Safari

Name 也可以使用带有内部文本的属性元素语法来设置,但这并不常见。相反,x:Name 不能在 XAML 属性元素语法中设置,也不能在使用 SetValue 的代码中设置;它只能使用对象的属性语法来设置,因为它是一个指令
如果 Name 可用作类的属性,则 Namex:Name 可以互换用作属性,但如果两者都在同一个上指定,则会导致解析异常元素。如果 XAML 是标记编译的,则异常将在标记编译时发生,否则在加载时发生。


D
DaFois

我的研究是 x:Name 作为 global 变量。但是,Name 作为 local 变量。这是否意味着 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}" />

您不能将 ButtonBinding 属性 Content 命名为“btn”,因为它在 StackPanel 之外