У WPF, які відмінності між атрибутами x: ім'я та ім'я?


573

У заголовку все сказано. Іноді здається, що атрибути Nameта x:Nameатрибути взаємозамінні.

Отже, які є остаточні відмінності між ними, і коли краще використовувати одне над іншим?

Чи є якісь наслідки для продуктивності чи пам'яті, щоб використовувати їх неправильно?


Відповіді говорять про те, що використовувати x:Nameвесь час працює добре. Я просто повинен був змінити його, Nameінакше я не міг посилатись на контроль у своєму .xaml.cs-коді, тому я буду припускати, що це вже не так, що він працює весь час добре.
Ортунд

1
Що стосується вашого відкату, який додатковий зміст надається фразі "заголовок каже все", Дрю? Хіба це не зайве? (Моя причина редагування полягає в тому, що я схильний відмовляти розмовним фразовим наповнювачам - це не більш інформативно, ніж "Цікаво, чи можете ви мені допомогти").
півзахисник

Відповіді:


481

Насправді є лише одне ім'я в XAML, the x:Name. Рамка, наприклад WPF, може необов'язково відображати одне зі своїх властивостей у XAML, x:Nameвикористовуючи RuntimeNamePropertyAttributeклас класу, який позначає один із властивостей класів як відображення до атрибута X: Name XAML.

Причиною цього було те, що дозволили створити рамки, які вже мають поняття "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: Ім'я , AutomationProperties.Name використовується інструментами доступності та деякими інструментами тестування.


2
У Visual Studio 2010 властивість Name встановлюється (не x: ім'я), коли ви редагуєте XAML через конструктор. Схоже, що MS заохочує використовувати ім'я через x: name, тому я гадаю, що це стандарт дефакто.
Туманність

11
Я не думаю, що вони взагалі взаємозамінні. Іменування елементів керування користувачами вимагає, x:Nameоскільки Nameце не створило б поле для розпізнавання в коді. Я все ще не знаю, чому це відбувається.
Лібор

5
Вони не є, ні я мав на увазі, що вони це зробили. У WPF, якщо елемент має Nameвластивість, він означає те саме. Якщо елемент не має Nameвластивості, ви повинні використовувати x:Name.
chuckj

90

Вони не одне і те ж.

x:Nameявляє собою поняття xaml, яке використовується в основному для опорних елементів. Коли ви надаєте елементу атрибут x: x:Namename xaml, "зазначене стає ім'ям поля, яке створюється в базовому коді при обробці xaml, і це поле містить посилання на об'єкт." ( MSDN ) Отже, це поле, створене дизайнером, яке за замовчуванням має внутрішній доступ.

Nameє існуючим рядковим властивістю FrameworkElement, переліченим як будь-яке інше властивість елемента wpf у вигляді атрибута xaml.

Як наслідок, це також x:Nameможе бути використане для більш широкого кола об'єктів. Це техніка, яка дозволяє будь-що в xaml посилатися на задане ім'я.


6
То чому ж можна використовувати Ім'я або x: Ім'я з Binding.ElementName? Здається, що атрибут x: name використовується не тільки для імені поля в згенерованому коді, але і для метаданих під час виконання.
Дрю Ноакс

Це генероване поле, як поле Ім'я у властивостях дизайну редактора WinForms. Там ви розміщуєте ім'я у списку властивостей, і воно стає назвою поля. Це та сама поведінка. Звичайно, він доступний під час виконання, оскільки це внутрішнє поле, зібране в код позаду. Binding.ElementName перевіряє будь-який випадок, тобто редактор xaml "магія", x: ім'я саме по собі не є магічним.
Kenan EK

39

x: Ім'я та ім'я посилаються на різні простори імен.

x: name - це посилання на простір імен x, визначений за замовчуванням у верхній частині файлу Xaml.

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


Гаразд давайте поглянемо на це по-іншому. Скажіть, ви перетягуєте кнопку на свою сторінку Xaml. Ви можете посилатися на це 2 способи x: ім'я та ім'я . Усі xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" та xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml" - це посилання на кілька просторів імен . Оскільки xaml містить простір імен Control (не 100% на це), а презентація містить FrameworkElement І клас клавіш має шаблон успадкування:

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

Отже, як можна було б очікувати, що все, що успадковується від FrameworkElement, матиме доступ до всіх його публічних атрибутів. тож у випадку з кнопкою він отримує свій атрибут Name від FrameworkElement, на самому верху дерева ієрархії. Таким чином, ви можете сказати x: ім'я або ім'я, і вони обидва матимуть доступ до геттера / сетера з FrameworkElement.

Довідник MSDN

WPF визначає атрибут CLR, який споживається процесорами XAML для того, щоб зіставити кілька просторів імен CLR в єдиний простір імен XML. Атрибут XmlnsDefinitionAttribute розміщується на рівні складання у вихідному коді, який виробляє збірку. Вихідний код збірки WPF використовує цей атрибут для відображення різних загальних просторів імен, таких як System.Windows та System.Windows.Controls, на http://schemas.microsoft.com/winfx/2006/xaml/presentationpace .

Тож атрибути збірки будуть виглядати приблизно так:

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")]  

1
Я не думаю, що це правда, що http://schemas.microsoft.com/winfx/2006/xamlмає місце, Controlоскільки ви можете використовувати його безпосередньо в XAML без простору імен "x":<Control />
Drew Noakes

23

Вони обидва те саме, що багато елементів рамки самі виявляють властивість імені, але для тих, хто цього не робить, ви можете використовувати x: name - я зазвичай дотримуюся x: name, тому що він працює для всього.

Якщо вони хочуть, елементи керування можуть називати себе властивістю залежності (тому що їм потрібно використовувати цю властивість залежно від внутрішніх справ), або вони не можуть вирішити.

Детальніше у msdn тут і тут :

Деякі програми рамкового рівня WPF можуть уникнути будь-якого використання атрибута x: Name, оскільки властивість залежності імені, визначена в просторі імен WPF для кількох важливих базових класів, таких як FrameworkElement / FrameworkContentElement, задовольняє цій самій цілі. Існує ще декілька загальних сценаріїв XAML та фреймворків, коли доступ коду до елемента без властивості Name необхідний, особливо це стосується певних класів підтримки анімації та розкладок. Наприклад, вам слід вказати x: ім'я на часових межах та перетвореннях, створених у XAML, якщо ви маєте намір посилатися на них з коду.

Якщо Ім'я доступне як властивість для класу, Ім'я та х: Ім'я може використовуватися взаємозамінно як атрибути, але помилка призведе, якщо обидва вказані на одному елементі.


4
Якщо різниці немає, то чому б існували два способи робити те саме? Обидва способи існували в першому випуску WPF.
Дрю Ноакс

@Steve, я не спростував жодної відповіді на це питання, хоча жоден з них до цих пір був не дуже підходящим.
Дрю Ноакс

Я не бачу, як відповідь, яка не тільки дає вам відповідь, але і дає посилання на MSDN для отримання додаткової інформації по темі, не підходить? :-)
Стівен Роббінс

5
@Встановіть свою оригінальну відповідь не на адресу мого питання, звідси і мій коментар. Я не шукаю сліпої віри "роби це так", а швидше проникливу відповідь, яка пояснювала, чому існують два способи, навіть якщо один із них працює весь час. Технічно правильно! = Відповідно. Ваше оновлення набагато краще.
Дрю Ноакс

1
Приблизно однакова відповідь тут: wpfwiki.com/WPF%20Q16.4.ashx x: Імена дають керуючим ім'ям, яке потрібно використовувати в списку коду. Деякі класи надаватимуть властивість Name з тією ж метою. Для цих класів різниці між x: ім'ям та іменем немає.
Вегар

11

X: Ім'я може спричинити проблеми з пам'яттю, якщо у вас є власні елементи керування. Він збереже пам'ять для запису NameScope.

Я кажу, що ніколи не використовуйте х: Ім'я, якщо не потрібно.


Домовились. Працював над додатком для кіоску, який мав численні витоки пам'яті, а попередня резолюція команди розробників полягала лише в тому, щоб примусити перезавантажити. Значну частину витоків було легко виявити. Однак після виправлення даних, знайдених за допомогою IntelliTrace та JustTrace, деякі відмови все-таки уникають неявного та явного вивезення сміття. Я читав: support.scichart.com/index.php?/News/NewsItem/View/21/… Виявив, що зменшення x: Name ще більше покращило продуктивність.
MachinusX

2
Це, наскільки я розумію, це впливає і на ім'я, і на x: ім'я, оскільки обидва додаються до NameScope. Якщо вам потрібне Ім'я на вашому елементі, його не обійти. Ви можете повторно ввести код у елементі без імені через FrameworkElement.RegisterName("elementname"). Однак, якщо ви FrameworkElement.UnregisterName("elementname")її зателефонуєте, це може бути "знешкоджено".
Адам Порожня

8

Єдина відмінність полягає в тому, що якщо ви використовуєте елементи керування користувача для управління з тієї ж збірки, то Ім'я не визначить ваш елемент управління, і ви отримаєте помилку "Використовувати х: ім'я для елементів управління в одній збірці". Отже x: ім'я - це версія WPF для управління іменами в WPF. Назва просто використовується як спадщина Winform. Вони хотіли розмежовувати найменування елементів керування у форматі WPF та winforms, оскільки вони використовують атрибути в Xaml для ідентифікації елементів керування від інших збірок, які вони використовували x: для імен управління.

Просто пам’ятайте, що не вводьте ім'я для елемента керування лише задля збереження його, оскільки воно залишається в пам’яті як порожнє, і це дасть вам попередження про те, що ім’я було застосовано до елемента керування, але його ніколи не застосовували.


8

Ім'я :

  1. може використовуватися лише для нащадків FrameworkElement та FrameworkContentElement;
  2. можна встановити з коду позаду через SetValue () та властивість.

x: Ім'я :

  1. може використовуватися майже для всіх елементів XAML;
  2. НЕ можна встановлювати з коду позаду через SetValue (); його можна встановити лише за допомогою синтаксису атрибутів на об'єктах, оскільки це директива.

Використання обох директив у XAML для одного FrameworkElement або FrameworkContentElement спричинить виняток: якщо компіляція розмітки XAML складена, виняток відбуватиметься при компіляції розмітки, інакше це відбувається при завантаженні.


7

x:Name означає: створити поле в коді позаду, щоб містити посилання на цей об’єкт.

Name означає: встановити властивість імені цього об'єкта.


Це не зовсім вірно; вони обидва доступні з коду, що знаходиться позаду, але що цікаво, лише x: ім'я може бути оновлено під час виконання. Горіх.

4

Я завжди використовую варіант x: name. Я поняття не маю, чи це впливає на якісь показники, мені просто легше з наступної причини. Якщо у вас є власні контролери користувачів, які перебувають в іншій збірці, властивості "Ім'я" не завжди буде достатньою. Це полегшує також дотримуватися властивість x: Name.


4
Якщо різниці немає, то чому б існували два способи робити те саме? Обидва способи існували в першому випуску WPF.
Дрю Ноакс

3

Це не елемент WPF, а стандартний XML, і BtBh правильно відповів на нього, x посилається на простір імен за замовчуванням. У XML, коли ви не маєте префіксу елемента / атрибута з простором імен, він передбачає, що ви бажаєте простору імен за замовчуванням. Тож введення тексту Name- це не що інше, як коротка рука x:Name. Детальніше про простори імен XML можна знайти в тексті посилання


Спокуса -1 x: посилається на інший простір імен XML, правда, але це насправді не корисна відповідь на Q, що стосується того, коли вам потрібно використовувати не один, ні інший. : /
Тім Ловелл-Сміт

2

Один з відповідей полягає в тому, що x: name має використовуватися в різних мовах програми, таких як c #, а ім'я має використовуватися для фреймворку. Чесно кажучи, це мені здається.


2

Зазначене x: ім'я стає ім'ям поля, яке створюється в базовому коді під час обробки XAML, і це поле містить посилання на об'єкт. У Silverlight, використовуючи керований API, процес створення цього поля виконується цільовими кроками MSBuild, які також відповідають за приєднання до часткових класів для файлу XAML та його коду. Ця поведінка не обов'язково визначається мовою XAML; саме Silverlight застосовує для використання x: Name у своїх моделях програмування та застосування.

Детальніше про MSDN ...


2

Коли ви оголошуєте елемент Button у XAML, ви посилаєтесь на клас, визначений у часі запуску Windows, який називається Button.

Кнопка має багато атрибутів, таких як фон, текст, поле, ..... і атрибут під назвою Name.

Тепер, коли ви оголошуєте Кнопку в XAML, це як створення анонімного об'єкта, у якого трапився атрибут під назвою Name.

Як правило, ви не можете посилатися на анонімний об'єкт, але в рамках WPF-процесора XAML дозволяє вам посилатися на цей об'єкт за будь-яким значенням, яке ви надали атрибуту Name.

Все йде нормально.

Інший спосіб створення об’єкта - це створення названого об'єкта замість анонімного об’єкта. У цьому випадку простір імен XAML має атрибут для об'єкта під назвою Name (а оскільки він знаходиться в просторі імен XAML, таким чином, ви маєте X :), який ви можете встановити, щоб ви могли ідентифікувати ваш об'єкт і звертатися до нього.

Висновок:

Ім'я - це атрибут конкретного об'єкта, але X: ім'я - це один атрибут цього об'єкта (є клас, який визначає загальний об'єкт).


0

Мої дослідження в x:Nameякості глобальної змінної. Однак Nameяк локальна змінна. Чи означає це: x: Ім'я ви можете викликати його будь-де у вашому XAML-файлі, але ім'я - ні.
Приклад:

<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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.