No WPF, quais são as diferenças entre os atributos x: Name e Name?

574

O título diz tudo. Às vezes, parece que os atributos Namee x:Namesão intercambiáveis.

Então, quais são as diferenças definitivas entre eles e quando é preferível usar um sobre o outro?

Há implicações de desempenho ou memória para usá-las da maneira errada?

Drew Noakes
fonte
As respostas sugerem que usar x:Nameo tempo todo funciona bem. Eu apenas tive que alterá-lo para o Namecontrário, não pude referenciar o controle no meu código .xaml.cs, portanto, assumirei que não é mais o caso de funcionar bem o tempo todo.
Ortund
1
Em relação à sua reversão, que significado extra é atribuído pela frase "o título já diz tudo", Drew? Não é redundante? (Meu motivo para editar é que eu tendem a desencorajar frases de preenchimento de conversação - isso não é mais informativo do que "eu me pergunto se você pode me ajudar").
junta

Respostas:

481

Realmente existe apenas um nome no XAML, o x:Name. Uma estrutura, como o WPF, pode opcionalmente mapear uma de suas propriedades para XAMLs x:Nameusando RuntimeNamePropertyAttributeon na classe que designa uma das propriedades de classes como mapeamento para o atributo x: Name de XAML.

O motivo disso foi permitir estruturas que já possuem um conceito de "Nome" em tempo de execução, como o WPF. No WPF, por exemplo, FrameworkElementintroduz uma propriedade Name.

Em geral, uma classe não precisa armazenar o nome para x:Nameser utilizável. Todos os x:Namemeios para XAML são gerar um campo para armazenar o valor no código por trás da classe. O que o tempo de execução faz com esse mapeamento depende da estrutura.

Então, por que existem duas maneiras de fazer a mesma coisa? A resposta simples é porque existem dois conceitos mapeados em uma propriedade. O WPF deseja preservar o nome de um elemento em tempo de execução (que pode ser usado por meio do Bind, entre outras coisas) e o XAML precisa saber quais elementos você deseja que sejam acessíveis pelos campos no código por trás da classe. O WPF vincula esses dois marcando a propriedade Name como um alias de x: Name.

No futuro, o XAML terá mais usos para x: Name, como permitir que você defina propriedades consultando outros objetos por nome, mas no 3.5 e anterior, ele é usado apenas para criar campos.

Se você deve usar uma ou outra é realmente uma questão de estilo, não técnica. Deixo isso para outras pessoas para uma recomendação.

Consulte também AutomationProperties.Name VS x: Name , AutomationProperties.Name é usado por ferramentas de acessibilidade e algumas ferramentas de teste.

chuckj
fonte
2
No Visual Studio 2010, a propriedade Name é definida (não x: Name) quando você edita o XAML por meio do designer. Parece que a MS incentiva o uso de Name sobre x: Name, então acho que esse é o padrão padrão.
Nebulosa
11
Eu não acho que os dois sejam intercambiáveis ​​em geral. A nomeação de controles de usuário exige x:Nameporque Namenão criaria um campo para ser reconhecido no code-behind. Ainda não sei por que isso acontece.
Libor
5
Eles não são nem eu quis dizer que sim. No WPF, se um elemento tem uma Namepropriedade, eles significam a mesma coisa. Se o elemento não tiver uma Namepropriedade, você deverá usar x:Name.
chuckj
90

Eles não são a mesma coisa.

x:Nameé um conceito xaml, usado principalmente para referenciar elementos. Quando você atribui a um elemento o atributo x: Name xaml ", o especificado x:Namese torna o nome de um campo criado no código subjacente quando o xaml é processado e esse campo mantém uma referência ao objeto". ( MSDN ) Portanto, é um campo gerado pelo designer, que possui acesso interno por padrão.

Nameé a propriedade de cadeia existente de a FrameworkElement, listada como qualquer outra propriedade do elemento wpf na forma de um atributo xaml.

Como conseqüência, isso também significa que x:Namepode ser usado em uma ampla gama de objetos. Essa é uma técnica para permitir que qualquer coisa no xaml seja referenciada por um determinado nome.

Kenan EK
fonte
6
Então, por que o Nome ou x: Nome pode ser usado com Binding.ElementName? Parece que o atributo x: Name não é usado apenas para nomear um campo no código gerado, mas também está disponível nos metadados no tempo de execução.
de Drew Noakes
É um campo gerado como o nome do campo nas propriedades de design do editor WinForms. Lá, você coloca um nome na lista de propriedades e ele se torna o nome de um campo. Esse é o mesmo comportamento. Obviamente, ele está disponível em tempo de execução, pois é um campo interno compilado no código por trás. Binding.ElementName verifica os dois casos, ou seja, o editor xaml "magic", o x: Name não é mágico por si só.
Kenan EK
39

x: Nome e Nome estão referenciando diferentes espaços para nome.

x: name é uma referência ao espaço para nome x definido por padrão na parte superior do arquivo Xaml.

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

Apenas dizendo que Name usa o padrão abaixo do namespace.

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

x: Name está dizendo, use o namespace que possui o x alias. x é o padrão e a maioria das pessoas o deixa, mas você pode alterá-lo para o que quiser

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

então sua referência seria foo: name

Definir e usar namespaces no WPF


OK, vamos olhar para isso de uma maneira diferente. Digamos que você arraste e solte um botão na sua página Xaml. Você pode fazer referência a essas 2 maneiras x: nome e nome . Todos os xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" e xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml" são referências a vários espaços para nome . Como o xaml mantém o namespace Control (não 100%) e a apresentação mantém o FrameworkElement AND a classe Button possui um padrão de herança de:

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

Portanto, como seria de esperar, qualquer coisa herdada do FrameworkElement teria acesso a todos os seus atributos públicos. portanto, no caso de Button, ele obtém seu atributo Name de FrameworkElement, no topo da árvore da hierarquia. Então você pode dizer x: Name ou Name e os dois acessarão o getter / setter a partir do FrameworkElement.

Referência do MSDN

O WPF define um atributo CLR que é consumido pelos processadores XAML para mapear vários espaços para nome CLR em um único espaço para nome XML. O atributo XmlnsDefinitionAttribute é colocado no nível do assembly no código-fonte que produz o assembly. O código-fonte do assembly WPF usa esse atributo para mapear os vários namespaces comuns, como System.Windows e System.Windows.Controls, para o http://schemas.microsoft.com/winfx/2006/xaml/presentation namespace.

Portanto, os atributos da montagem serão parecidos com:

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")]  
cgreeno
fonte
1
Eu não acho que é verdade que http://schemas.microsoft.com/winfx/2006/xamldetém Controldesde que você pode usá-lo diretamente em XAML sem um 'x' namespace:<Control />
de Drew Noakes
23

Os dois são a mesma coisa, muitos elementos da estrutura expõem uma propriedade name, mas para aqueles que não usam, você pode usar x: name - eu geralmente fico com x: name, porque funciona para tudo.

Os controles podem expor o próprio nome como uma Propriedade de Dependência, se eles quiserem (porque precisam usar essa Propriedade de Dependência internamente) ou podem optar por não.

Mais detalhes no msdn aqui e aqui :

Alguns aplicativos em nível de estrutura do WPF podem evitar qualquer uso do atributo x: Name, porque a propriedade de dependência Name, conforme especificada no namespace do WPF, para várias classes de base importantes, como FrameworkElement / FrameworkContentElement, atende a esse mesmo objetivo. Ainda existem alguns cenários comuns de XAML e estrutura em que o acesso do código a um elemento sem propriedade Name é necessário, principalmente em determinadas classes de animação e suporte de storyboard. Por exemplo, você deve especificar x: Name nas linhas do tempo e nas transformações criadas em XAML, se pretender referenciá-las a partir do código.

Se Name estiver disponível como uma propriedade na classe, Name e x: Name poderão ser usados ​​de forma intercambiável como atributos, mas ocorrerá um erro se ambos forem especificados no mesmo elemento.

Steven Robbins
fonte
4
Se não há diferença, por que haveria duas maneiras de fazer a mesma coisa? As duas formas existiam no primeiro lançamento do WPF.
Desenhou Noakes
@ Steve, eu não votei nenhuma das respostas sobre esta questão, mesmo que nenhuma delas tenha sido até agora muito apropriada.
Desenhou Noakes
Não vejo como uma resposta que não apenas fornece a resposta, mas também fornece links para o MSDN para obter mais informações sobre o tópico, não é apropriado? :-)
Steven Robbins
5
@ Steve, sua resposta original não abordou minha pergunta, portanto, meu comentário. Não estou procurando por fé cega "faça desta maneira", mas sim uma resposta perspicaz que explique por que existem duas maneiras, mesmo que uma delas funcione o tempo todo. Tecnicamente correto! = Apropriado. Sua atualização é muito melhor.
Desenhou Noakes
1
A mesma resposta aqui: wpfwiki.com/WPF%20Q16.4.ashx x: Name está dando ao controle um nome para usar no code-behind. Algumas classes fornecerão uma propriedade Name para o mesmo objetivo. Para essas classes, não há diferença entre x: nome e nome.
Vegar
11

X: O nome pode causar problemas de memória se você tiver controles personalizados. Ele manterá um local de memória para a entrada do NameScope.

Eu digo nunca use x: Name, a menos que você precise.

Scott
fonte
Acordado. Trabalhei em um aplicativo de quiosque com inúmeras falhas de memória e a resolução anterior da equipe de desenvolvimento era apenas para forçar uma reinicialização. Muitos dos vazamentos foram facilmente identificados. No entanto, depois de corrigir os encontrados via IntelliTrace e JustTrace, alguns árbitros ainda evitam a coleta de lixo implícita e explícita. Eu li: support.scichart.com/index.php?/News/NewsItem/View/21/… Descobri que reduzir x: Name melhorava ainda mais o desempenho.
precisa saber é o seguinte
2
No meu entender, isso afeta o Name e x: Name, pois ambos são adicionados ao NameScope. Se você precisar de um nome em seu elemento, não há como evitar isso. Você pode reproduzir novamente o código em um elemento sem nome via FrameworkElement.RegisterName("elementname"). No entanto, se você ligar FrameworkElement.UnregisterName("elementname"), pode ser "desreferenciado".
precisa
8

A única diferença é que, se você estiver usando controles de usuário em um controle do mesmo assembly, o Name não identificará seu controle e você receberá um erro "Use x: Name para controles no mesmo assembly". Então x: Name é a versão WPF dos controles de nomenclatura no WPF. O nome é usado apenas como um legado do Winform. Eles queriam diferenciar a nomeação de controles no WPF e winforms, pois eles usam atributos no Xaml para identificar controles de outros assemblies que usaram x: for Names of control.

Lembre-se de não colocar um nome para um controle apenas para mantê-lo, pois ele reside na memória como um espaço em branco e você receberá um aviso de que Name foi aplicado a um controle, mas que nunca será usado.

Bipul Kumar
fonte
8

Nome :

  1. pode ser usado apenas para descendentes de FrameworkElement e FrameworkContentElement;
  2. pode ser definido a partir do code-behind via SetValue () e como propriedade.

x: Nome :

  1. pode ser usado para quase todos os elementos XAML;
  2. NÃO pode ser definido a partir do code-behind via SetValue (); só pode ser definido usando a sintaxe de atributo nos objetos, porque é uma diretiva.

O uso de ambas as diretivas no XAML para um FrameworkElement ou FrameworkContentElement causará uma exceção: se o XAML for compilado, a exceção ocorrerá na compilação da marcação, caso contrário, ocorrerá no carregamento.

Oleksandr Zolotarov
fonte
7

x:Name significa: crie um campo no código atrás para manter uma referência a esse objeto.

Name significa: defina a propriedade name deste objeto.

itzmebibin
fonte
Isso não é bem verdade; ambos são acessíveis a partir do código, mas, curiosamente, apenas o x: Name pode ser atualizado em tempo de execução. Noz.
4

Eu sempre uso a variante x: Name. Não faço ideia se isso afeta algum desempenho, mas acho mais fácil pelo seguinte motivo. Se você possui seus próprios controles de usuário que residem em outro assembly, apenas a propriedade "Nome" nem sempre é suficiente. Isso facilita a aderência também à propriedade x: Name.

Simon
fonte
4
Se não há diferença, por que haveria duas maneiras de fazer a mesma coisa? As duas formas existiam no primeiro lançamento do WPF.
Desenhou Noakes
3

Não é um item do WPF, mas um XML padrão e o BtBh respondeu corretamente, x refere-se ao espaço para nome padrão. No XML, quando você não prefixa um elemento / atributo com um espaço para nome, ele assume que deseja o espaço para nome padrão. Portanto, digitar apenas Namenão é mais que uma mão curta x:Name. Mais detalhes sobre espaços para nome XML podem ser encontrados no texto do link

Robert MacLean
fonte
Tentado a -1 x: refere-se a um espaço para nome XML diferente, é verdade, mas isso não é realmente uma resposta útil para o Q, que é sobre quando você precisa usar um não o outro. : /
Tim Lovell-Smith
2

Uma das respostas é que x: name deve ser usado dentro de diferentes linguagens de programa, como c #, e name, para ser usado na estrutura. Honestamente, é isso que me parece.

daddycardona
fonte
2

O x: Name especificado se torna o nome de um campo criado no código subjacente quando o XAML é processado e esse campo contém uma referência ao objeto. No Silverlight, usando a API gerenciada, o processo de criação desse campo é realizado pelas etapas de destino do MSBuild, que também são responsáveis ​​por ingressar nas classes parciais de um arquivo XAML e seu code-behind. Esse comportamento não é necessariamente especificado na linguagem XAML; é a implementação específica que o Silverlight aplica para usar x: Name em seus modelos de programação e aplicativo.

Leia mais no MSDN ...

Edd
fonte
2

Quando você declara um elemento Button em XAML, está se referindo a uma classe definida no tempo de execução do Windows chamada Button.

O botão possui muitos atributos, como plano de fundo, texto, margem, ..... e um atributo chamado Nome.

Agora, quando você declara um botão no XAML, é como criar um objeto anônimo que possuísse um atributo chamado Nome.

Em geral, você não pode se referir a um objeto anônimo, mas no processador XAML da estrutura WPF permite que você se refira a esse objeto por qualquer valor que você tenha dado ao atributo Nome.

Por enquanto, tudo bem.

Outra maneira de criar um objeto é criar um objeto nomeado em vez de um objeto anônimo. Nesse caso, o espaço para nome XAML possui um atributo para um objeto chamado Name (e, como está no espaço para nome XAML, possui X :) que você pode definir para identificar seu objeto e fazer referência a ele.

Conclusão:

Nome é um atributo de um objeto específico, mas X: Nome é um atributo desse objeto (há uma classe que define um objeto geral).

RockyMan Rocky
fonte
0

Minha pesquisa é x:Namecomo variável global . No entanto, Namecomo variável local . Isso significa x: Name, você pode chamá-lo em qualquer lugar do seu arquivo XAML, mas Name não.
Exemplo:

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

Você não pode Bindingpropriedade Contentde Buttoncom nome é "btn" porque foraStackPanel

Phuc Hoang
fonte