【问题标题】:In WPF, what are the differences between the x:Name and Name attributes?在 WPF 中,x:Name 和 Name 属性有什么区别?
【发布时间】:2010-10-10 01:06:05
【问题描述】:

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

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

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

【问题讨论】:

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

标签: .net wpf xaml name-attribute


【解决方案1】:

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")] 修饰。
【解决方案2】:

它们不是一回事。

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 解析器的限制。
【解决方案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:Name 是说使用具有 x 别名的命名空间。 x 是默认值,大多数人都会保留它,但您可以将其更改为您喜欢的任何内容

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

所以您的参考将是 foo:name

Define and Use Namespaces in WPF


好的,让我们换一种方式来看待这个问题。假设您将一个按钮拖放到您的 Xaml 页面上。您可以参考这两种方式 x:namename。所有 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 是对多个命名空间的引用。由于 xaml 拥有 Control 命名空间(不是 100%)并且 presentation 拥有 FrameworkElement按钮类有一个继承模式:

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 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 是真的,因为您可以在没有“x”命名空间的情况下直接在 XAML 中使用它:<Control />
【解决方案4】:

它们是相同的东西,很多框架元素本身都暴露了一个 name 属性,但对于那些没有的你可以使用 x:name - 我通常只坚持使用 x:name 因为它适用于所有东西。

如果他们愿意,控件可以将自己暴露为依赖属性(因为他们需要在内部使用该依赖属性),或者他们可以选择不这样做。

msdn herehere 中的更多详细信息:

一些 WPF 框架级应用程序 可能能够避免任何使用 x:Name 属性,因为 Name 指定的依赖属性 在 WPF 命名空间中有几个 重要的基类,例如 框架元素/框架内容元素 满足同样的目的。有 还是一些常见的 XAML 和框架 代码访问的场景 没有 Name 属性的元素是 必要的,尤其是在某些情况下 动画和故事板支持 类。例如,你应该 在时间轴上指定 x:Name 和 在 XAML 中创建的转换,如果您 打算从代码中引用它们。

如果名称作为属性可用 可以使用类、Name 和 x:Name 可互换地作为属性,但 如果两者都是,将导致错误 在同一元素上指定。

【讨论】:

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

如果您有自定义控件,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"),它可以被“取消引用”。
【解决方案6】:

姓名

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

x:姓名

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

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

【讨论】:

    【解决方案7】:

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

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

    【讨论】:

      【解决方案8】:

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

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

      【讨论】:

      • 这不是真的;它们都可以从代码隐藏中访问,但有趣的是,只有 x:Name 可以在运行时更新。坚果。
      【解决方案9】:

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

      【讨论】:

      • 如果没有区别,那为什么会有两种方法来做同样的事情呢?这两种方式都存在于 WPF 的第一个版本中。
      【解决方案10】:

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

      【讨论】:

      • Tempted to -1 x: 指的是不同的 XML 命名空间,是的,但这实际上并不是对 Q 的有用答案,即您何时需要不使用另一个。 ://
      【解决方案11】:

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

      Read More on MSDN...

      【讨论】:

        【解决方案12】:

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

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

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

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

        到目前为止一切顺利。

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

        结论:

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

        【讨论】:

          【解决方案13】:

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

          【讨论】:

            【解决方案14】:

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

            【讨论】:

              【解决方案15】:

              我的研究是 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}" />
              

              你不能 Binding 属性 ContentButton 名称是“btn”,因为它在 StackPanel 之外

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2014-07-19
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2020-04-03
                • 2011-01-28
                相关资源
                最近更新 更多