Проблема с именованием корневого элемента 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>
примечание: для ясности я не определял MarkupExtension
в пространстве имен; использование пустого псевдонима clr-namespace
, как показано здесь, d̲o̲e̲s̲ фактически работает для доступа к пространству имен global::
(хотя дизайнер VS2013, кажется, жалуется на это).
Результат:
Окно, содержимое которого связано само с собой.
Примечание
person
Glenn Slayden
schedule
19.12.2014