Jakie są różnice w WPF między atrybutami x: Nazwa i Nazwa?

573

Tytuł mówi wszystko. Czasami wydaje się, że atrybuty Namei x:Namesą wymienne.

Jakie są zatem ostateczne różnice między nimi i kiedy lepiej jest używać jednego nad drugim?

Czy są jakieś konsekwencje związane z wydajnością lub pamięcią związane z niewłaściwym ich użyciem?

Drew Noakes
źródło
Odpowiedzi sugerują, że korzystanie przez x:Namecały czas działa dobrze. Po prostu musiałem to zmienić, Nameinaczej nie mogłem odwoływać się do kontrolki w moim kodzie .xaml.cs, więc założę, że nie jest tak, że cały czas działa dobrze.
Ortund
1
Co do twojego wycofania, jakie dodatkowe znaczenie nadaje zwrot „tytuł mówi wszystko”, Drew? Czy to nie jest zbędne? (Moim powodem do edycji jest to, że odradzam konwersacyjne frazy wypełniające - nie jest to bardziej pouczające niż „Zastanawiam się, czy możesz mi pomóc”).
halfer

Odpowiedzi:

481

Tam naprawdę jest tylko jedna nazwa w XAML, x:Name. Środowisko, takie jak WPF, może opcjonalnie odwzorować jedną ze swoich właściwości na XAML, x:Nameużywając RuntimeNamePropertyAttributeklasy, która wyznacza jedną z właściwości klas jako odwzorowanie na atrybut x: Name XAML.

Powodem tego było zezwolenie na frameworki, które już mają pojęcie „Nazwa” w czasie wykonywania, takie jak WPF. Na przykład w WPF FrameworkElementwprowadza właściwość Name.

Zasadniczo klasa nie musi przechowywać nazwy, x:Nameaby była użyteczna. Wszystkie x:Nameśrodki do XAML to generowanie pola do przechowywania wartości w kodzie za klasą. To, co środowisko wykonawcze robi z tym odwzorowaniem, zależy od struktury.

Dlaczego istnieją dwa sposoby na zrobienie tego samego? Prosta odpowiedź polega na tym, że istnieją dwie koncepcje mapowane na jedną właściwość. WPF chce, aby nazwa elementu została zachowana w środowisku wykonawczym (między innymi przez Bind), a XAML musi wiedzieć, jakie elementy mają być dostępne dla pól w kodzie za klasą. WPF łączy te dwa elementy, zaznaczając właściwość Name jako alias x: Nazwa.

W przyszłości XAML będzie miał więcej zastosowań dla x: Nazwa, na przykład umożliwiając ustawianie właściwości poprzez odwoływanie się do innych obiektów według nazwy, ale w 3.5 i wcześniejszych wersjach jest używany tylko do tworzenia pól.

To, czy powinieneś użyć jednego, czy drugiego, jest naprawdę pytaniem stylowym, a nie technicznym. Pozostawiam to innym do rekomendacji.

Zobacz także AutomationProperties.Name VS x: Nazwa , AutomationProperties.Name jest używany przez narzędzia ułatwień dostępu i niektóre narzędzia testujące.

chuckj
źródło
2
W Visual Studio 2010 właściwość Nazwa jest ustawiona (nie x: Nazwa) podczas edycji XAML za pomocą projektanta. Wygląda na to, że MS zachęca do korzystania z Name nad x: Name, więc myślę, że to jest standard defacto.
Mgławica
11
Nie sądzę, że te dwa są ogólnie wymienne. Nazwy elementów sterujących użytkownika wymagają, x:Nameponieważ Namenie utworzyłyby pola, które byłoby rozpoznawane w kodach. Jednak wciąż nie wiem, dlaczego tak się dzieje.
Libor
5
Nie są ani nie chciałem sugerować, że tak. W WPF, jeśli element ma Namewłaściwość, oznacza to to samo. Jeśli element nie ma Namewłaściwości, musisz użyć x:Name.
chuckj
90

To nie to samo.

x:Nameto koncepcja xaml, stosowana głównie do elementów odniesienia. Gdy podasz elementowi atrybut x: Name xaml, „podana x:Namenazwa będzie nazwą pola, które jest tworzone w kodzie leżącym u podstaw przetwarzania, gdy xaml jest przetwarzany, a pole to zawiera odniesienie do obiektu”. ( MSDN ) Jest to pole generowane przez projektanta, które domyślnie ma dostęp wewnętrzny.

Nameto istniejąca właściwość ciągu z FrameworkElement, wymieniona jako dowolna inna właściwość elementu wpf w postaci atrybutu xaml.

W konsekwencji oznacza to również, że x:Namemożna go stosować do szerszego zakresu obiektów. Jest to technika umożliwiająca odwoływanie się do czegokolwiek w Xaml przez daną nazwę.

Kenan EK
źródło
6
Dlaczego więc nazwa lub x: nazwa mogą być używane z Binding.ElementName? Wygląda na to, że atrybut x: Nazwa służy nie tylko do nazwania pola w wygenerowanym kodzie, ale jest także dostępny w metadanych w czasie wykonywania.
Drew Noakes,
Jest to pole generowane, takie jak pole Nazwa we właściwościach projektowych edytora WinForms. Tam umieszczasz nazwę na liście właściwości, która staje się nazwą pola. To jest to samo zachowanie. Oczywiście jest on dostępny w czasie wykonywania, ponieważ jest to wewnętrzne pole wkompilowane w kod z tyłu. Binding.ElementName sprawdza dla obu przypadków, czyli „magii” edytora xaml, x: Nazwa sama w sobie nie jest magiczna.
Kenan EK
39

x: Nazwa i Nazwa odnoszą się do różnych przestrzeni nazw.

x: nazwa jest odniesieniem do przestrzeni nazw x zdefiniowanej domyślnie w górnej części pliku Xaml.

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

Po prostu mówiąc Nazwa używa domyślnej przestrzeni nazw poniżej.

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

x: Nazwa mówi używać przestrzeni nazw, która ma alias x . x jest ustawieniem domyślnym i większość ludzi go opuszcza, ale możesz go zmienić na dowolny

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

więc twoim referencją będzie foo: name

Zdefiniuj i używaj przestrzeni nazw w WPF


OK, spójrzmy na to z innej perspektywy. Załóżmy, że przeciągasz i upuszczasz przycisk na swojej stronie Xaml. Możesz odwołać się do tych 2 sposobów x: nazwa i nazwa . Wszystkie xmlns = „http://schemas.microsoft.com/winfx/2006/xaml/presentation” i xmlns: x = „http://schemas.microsoft.com/winfx/2006/xaml” to odniesienia do wielu przestrzeni nazw . Ponieważ xaml posiada przestrzeń nazw Control (nie 100%), a prezentacja zawiera FrameworkElement ORAZ klasa Button ma wzorzec dziedziczenia:

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

Jak można się spodziewać, wszystko, co odziedziczy po FrameworkElement, miałoby dostęp do wszystkich jego publicznych atrybutów. więc w przypadku przycisku pobiera on swój atrybut Name z FrameworkElement, na samym szczycie drzewa hierarchii. Możesz więc powiedzieć x: Nazwa lub Nazwa, a oni będą mieli dostęp do gettera / settera z FrameworkElement.

Dokumentacja MSDN

WPF definiuje atrybut CLR używany przez procesory XAML w celu mapowania wielu przestrzeni nazw CLR do pojedynczej przestrzeni nazw XML. XmlnsDefinitionAttribute atrybut jest umieszczony na poziomie montażowej w kodzie, który wytwarza się montaż. Kod źródłowy zestawu WPF używa tego atrybutu do mapowania różnych popularnych przestrzeni nazw, takich jak System.Windows i System.Windows.Controls, na http://schemas.microsoft.com/winfx/2006/xaml/presentation namespace.

Tak więc atrybuty zestawu będą wyglądać mniej więcej tak:

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
źródło
1
Nie sądzę, że to prawda, że http://schemas.microsoft.com/winfx/2006/xamlposiada Controlponieważ można go używać bezpośrednio w XAML bez „x” nazw:<Control />
Drew Noakes
23

Oba są takie same, wiele elementów frameworka sama wystawia właściwość name, ale dla tych, którzy nie mogą używać x: name - zwykle trzymam się x: name, ponieważ działa na wszystko.

Kontrolki mogą ujawniać nazwę jako Właściwość Zależności, jeśli chcą (ponieważ muszą używać tej Własności Zależności wewnętrznie), lub mogą tego nie robić.

Więcej informacji w msdn tutaj i tutaj :

Niektóre aplikacje na poziomie frameworku WPF mogą być w stanie uniknąć użycia atrybutu x: Name, ponieważ właściwość zależności Nazwa określona w przestrzeni nazw WPF dla kilku ważnych klas podstawowych, takich jak FrameworkElement / FrameworkContentElement, spełnia ten sam cel. Nadal istnieje kilka typowych scenariuszy XAML i frameworka, w których wymagany jest dostęp do kodu elementu bez właściwości Name, zwłaszcza w niektórych klasach obsługi animacji i scenariuszy. Na przykład powinieneś podać x: Nazwa na osiach czasu i transformacjach utworzonych w XAML, jeśli zamierzasz odwoływać się do nich z kodu.

Jeśli Nazwa jest dostępna jako właściwość w klasie, Nazwa i x: Nazwa mogą być używane zamiennie jako atrybuty, ale wystąpi błąd, jeśli oba zostaną określone w tym samym elemencie.

Steven Robbins
źródło
4
Jeśli nie ma różnicy, to dlaczego istnieją dwa sposoby robienia tego samego? Oba sposoby istniały w pierwszej wersji WPF.
Drew Noakes
@ Steve, nie głosowałem żadnej z odpowiedzi na to pytanie, mimo że żadna z nich nie była jak dotąd odpowiednia.
Drew Noakes
Nie rozumiem, w jaki sposób odpowiedź, która nie tylko daje odpowiedź, ale także daje linki do MSDN, aby uzyskać więcej informacji na ten temat, nie jest odpowiednia? :-)
Steven Robbins
5
@Steve oryginalna odpowiedź nie dotyczyła mojego pytania, stąd mój komentarz. Nie szukam ślepej wiary „zrób to w ten sposób”, ale raczej wnikliwą odpowiedź, która wyjaśniła, dlaczego istnieją dwa sposoby, nawet jeśli jeden z nich cały czas działa. Technicznie poprawne! = Odpowiednie. Twoja aktualizacja jest znacznie lepsza.
Drew Noakes
1
Bardzo podobna odpowiedź tutaj: wpfwiki.com/WPF%20Q16.4.ashx x: Nazwa nadaje kontrolce nazwę, która ma być używana w przypadku kodu. Niektóre klasy zapewnią właściwość Name w tym samym celu. W przypadku tych klas nie ma różnicy między x: nazwa i nazwa.
Vegar
11

X: Nazwa może powodować problemy z pamięcią, jeśli masz niestandardowe elementy sterujące. Zachowa miejsce w pamięci dla pozycji NameScope.

Mówię, że nigdy nie używaj x: Nazwa, chyba że musisz.

Scott
źródło
Zgoda. Pracowałem nad aplikacją kiosku, która miała wiele przecieków pamięci, a rezolucja poprzedniego zespołu programistów miała po prostu wymusić ponowne uruchomienie. Wiele wycieków można było łatwo zidentyfikować. Jednak po naprawieniu tych znalezionych za pomocą IntelliTrace i JustTrace, niektóre referencje wciąż wymykały się niejawnemu i jawnemu wyrzucaniu elementów bezużytecznych. Przeczytałem: support.scichart.com/index.php?/News/NewsItem/View/21/... Stwierdziłem, że zmniejszenie x: Nazwa dodatkowo poprawia wydajność.
MachinusX
2
Rozumiem, że wpływa to zarówno na Name, jak i x: Name, ponieważ oba są dodawane do NameScope. Jeśli potrzebujesz Nazwy na swoim elemencie, nie można go obejść. Można powtórzenia błędu w kodzie na element bez nazwy poprzez FrameworkElement.RegisterName("elementname"). Jeśli jednak zadzwonisz FrameworkElement.UnregisterName("elementname"), możesz go „odnieść”.
Adam Caviness,
8

Jedyną różnicą jest to, że jeśli używasz formantów użytkownika do sterowania z samego zespołu następnie Nazwa nie będzie zidentyfikować kontrolę, a otrzymasz błąd „use x: Name do kontroli w tym samym Zgromadzenie”. Więc x: Nazwa jest wersją WPF kontroli nazewnictwa w WPF. Nazwa jest po prostu używana jako dziedzictwo Winform. Chcieli odróżnić nazewnictwo formantów w WPF i formach win, ponieważ używają atrybutów w Xaml do identyfikowania formantów z innych zespołów, których używali x: dla nazw kontroli.

Pamiętaj tylko, aby nie umieszczać nazwy kontrolki tylko dla zachowania jej, ponieważ znajduje się ona w pamięci jako pusta, a wyświetli ostrzeżenie, że Nazwa została zastosowana do kontrolki, ale nigdy jej nie użyto.

Bipul Kumar
źródło
8

Imię :

  1. może być używany tylko dla potomków FrameworkElement i FrameworkContentElement;
  2. można ustawić od kodu za pomocą SetValue () i podobnie do właściwości.

x: Nazwa :

  1. może być stosowany do prawie wszystkich elementów XAML;
  2. Nie można ustawić z opóźnieniem kodu poprzez setValue (); można go ustawić tylko przy użyciu składni atrybutów na obiektach, ponieważ jest to dyrektywa.

Użycie obu dyrektyw w XAML dla jednego FrameworkElement lub FrameworkContentElement spowoduje wyjątek: jeśli XAML jest skompilowany ze znacznikami, wyjątek wystąpi na kompilacji znaczników, w przeciwnym razie nastąpi przy ładowaniu.

Ołeksandr Zołotarow
źródło
7

x:Name oznacza: utwórz pole w kodzie, aby przechowywać odniesienie do tego obiektu.

Name środki: ustawić właściwość nazwa tego obiektu.

itzmebibin
źródło
To nie do końca prawda; oba są dostępne od strony kodowej, ale co ciekawe, tylko x: Nazwa może być aktualizowana w czasie wykonywania. Orzechowy.
4

Zawsze używam wariantu x: Nazwa. Nie mam pojęcia, czy to wpływa na wydajność, ale po prostu jest mi łatwiej z następującego powodu. Jeśli masz własne elementy sterowania użytkownika, które znajdują się w innym zestawie, tylko właściwość „Nazwa” nie zawsze będzie wystarczająca. Ułatwia to po prostu przyklejenie właściwości x: Name.

Szymon
źródło
4
Jeśli nie ma różnicy, to dlaczego istnieją dwa sposoby robienia tego samego? Oba sposoby istniały w pierwszej wersji WPF.
Drew Noakes
3

To nie jest element WPF, ale standardowy XML i BtBh poprawnie na nie odpowiedział, x odnosi się do domyślnej przestrzeni nazw. W XML, gdy nie poprzedzasz elementu / atrybutu przestrzenią nazw, zakłada się, że chcesz domyślną przestrzeń nazw. Pisanie Namejest więc tylko krótką ręką x:Name. Więcej informacji na temat przestrzeni nazw XML można znaleźć w tekście łącza

Robert MacLean
źródło
Kuszony do -1 x: odnosi się do innej przestrzeni nazw XML, to prawda, ale tak naprawdę nie jest to przydatna odpowiedź na pytanie Q, kiedy chodzi o to, kiedy trzeba używać innych. : /
Tim Lovell-Smith
2

Jedną z odpowiedzi jest to, że x: nazwa ma być używana w różnych językach programu, takich jak c #, a nazwa ma być używana dla frameworka. Szczerze mówiąc, tak to dla mnie brzmi.

daddycardona
źródło
2

Określone x: Nazwa staje się nazwą pola, które jest tworzone w kodzie bazowym podczas przetwarzania XAML, a to pole zawiera odniesienie do obiektu. W Silverlight, przy użyciu zarządzanego interfejsu API, proces tworzenia tego pola jest wykonywany przez kroki docelowe MSBuild, które są również odpowiedzialne za dołączenie klas częściowych do pliku XAML i jego kodu. To zachowanie niekoniecznie jest określone w języku XAML; jest to szczególna implementacja, którą Silverlight stosuje do używania x: Nazwa w swoich modelach programowania i aplikacji.

Czytaj więcej na MSDN ...

Edd
źródło
2

Kiedy deklarujesz element Button w XAML, masz na myśli klasę zdefiniowaną w czasie wykonywania systemu Windows o nazwie Button.

Przycisk ma wiele atrybutów, takich jak tło, tekst, margines, ..... oraz atrybut o nazwie Nazwa.

Teraz, kiedy deklarujesz Button w XAML, przypomina tworzenie anonimowego obiektu, który akurat ma atrybut o nazwie Nazwa.

Zasadniczo nie można odwoływać się do anonimowego obiektu, ale w środowisku WPF procesor XAML umożliwia odwoływanie się do tego obiektu za pomocą dowolnej wartości podanej dla atrybutu Nazwa.

Na razie w porządku.

Innym sposobem utworzenia obiektu jest utworzenie obiektu o nazwie zamiast obiektu anonimowego. W tym przypadku nazw XAML ma atrybut dla obiektu o nazwie Nazwa (a ponieważ jest w przestrzeni nazw XAML mają tym samym X :), które można ustawić, dzięki czemu można zidentyfikować obiekt i odnoszą się do niego.

Wniosek:

Nazwa jest atrybutem obiektu konkretnego, ale X: Nazwa jest jednym atrybutem tego obiektu (jest klasa, która definiuje ogólne obiektu).

RockyMan Rocky
źródło
0

Moje badania są x:Namejak zmienna globalna . Jednak Namejako zmienna lokalna . Czy to oznacza, że ​​x: Nazwa można nazwać w dowolnym miejscu pliku XAML, ale Nazwa nie jest.
Przykład:

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

Nie możesz Bindingnieruchomość Contentstanowi Buttonz nazwy jest „btn”, ponieważ na zewnątrzStackPanel

Phuc Hoang
źródło