Проблема с присвоением имени корневому элементу XAML
заключается в том, что если вы привыкли использовать одно и то же имя (т. Е. "_This", "Root" и т. Д.) Для всех корни в вашем проекте, тогда позднее связывание во вложенных шаблонах может получить доступ к неправильному элементу. Это связано с тем, что, когда {Binding}
ElementName=...
используется в Template
, имена разрешаются во время выполнения путем перемещения по дереву NameScope
до тех пор, пока не будет найдено первое совпадение.
Решение Клинта избегает именования корневого элемента, но оно устанавливает корневой элемент в свой собственный DataContext
, что может быть невозможно, если DataContext необходим, скажем, для данных. Также кажется немного сложным ввести еще одну привязку к элементу только для обеспечения доступа к нему. Позже, если доступ больше не нужен, это {Binding}
станет беспорядком: ответственность за доступ должным образом будет связана с целью и связыванием.
Соответственно, вот простое расширение разметки для доступа к корневому элементу XAML без указания его имени:
using System.Xaml;
using System.Windows.Markup;
public sealed class XamlRootExtension : MarkupExtension
{
public override Object ProvideValue(IServiceProvider sp)
{
var rop = sp.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider;
return rop == null ? null : rop.RootObject;
}
};
XAML
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:global="clr-namespace:">
<TextBlock Text="{Binding Source={global:XamlRoot},Mode=OneTime}" />
</Window>
note : для ясности я не определил MarkupExtension
в пространстве имен; использование пустого псевдонима clr-namespace
, как показано здесь d̲o̲e̲s̲ фактически работает для доступа к пространству имен global::
(хотя дизайнер VS2013, похоже, жалуется на это).
Результат
Окно, содержимое которого связано с самим собой.
нотабене