RelativeSource работает с (вложенным) подсвойством, в то время как ElementName не
Проблема с кодом ниже: привязка к SomeClassProp.SubTextProp
не работает (свойство источника не устанавливается для содержимого текстового поля), а для TextProp
оно делает.
XAML:
<Window x:Class="TestWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Name="wMain"
SizeToContent="WidthAndHeight">
<StackPanel>
<TextBox Text="{Binding ElementName=wMain, Path=SomeClassProp.SubTextProp}" Width="120" Height="23" />
<TextBox Text="{Binding ElementName=wMain, Path=TextProp}" Width="120" Height="23" />
</StackPanel>
</Window>
и код:
public partial class MainWindow : Window
{
public SomeClass SomeClassProp { get; set; }
public string TextProp { get; set; }
public MainWindow()
{
InitializeComponent();
SomeClassProp = new SomeClass();
}
}
public class SomeClass
{
public string SubTextProp { get; set; }
}
Я что-то упускаю здесь очевидное?
Обратите внимание, что эта привязка необходима для работы от цели (текстовое поле) к источнику (свойство класса).
ОБНОВЛЕНИЕ: Когда я меняю привязку с ElementName=wMain
в RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}
- Обе привязки работают. Так что проблема специфична для ElementName
обязательное свойство.
1 ответ
Хорошо, наконец, я нашел проблему!
После добавления diag:PresentationTraceSources.TraceLevel=High
для привязки defs (кстати, очень полезная вещь, при отсутствии обычной пошаговой отладки) в выводе я увидел следующее:
Предупреждение System.Windows.Data: 108: BindingExpression (hash=54116930): на уровне 0 - для MainWindow.SomeClassProp найден метод доступа RuntimePropertyInfo(SomeClassProp) Предупреждение System.Windows.Data: 104: BindingExpression (hash=54116930): заменить элемент на уровне 0 на MainWindow (hash=47283970), используя метод доступа RuntimePropertyInfo(SomeClassProp) Предупреждение System.Windows.Data: 101: BindingExpression (hash=54116930): GetValue на уровне 0 из MainWindow (hash = 47283970) с использованием RuntimePropertyInfo(SomeClassProp): Предупреждение System.Windows.Data: 106: BindingExpression (hash=54116930): элемент на уровне 1 пуст - нет доступа Предупреждение System.Windows.Data: 80: BindingExpression (hash=54116930): TransferValue - получено необработанное значение {DependencyProperty.UnsetValue} Предупреждение System.Windows.Data: 88: BindingExpression (hash=54116930): TransferValue - использование запасного значения / значения по умолчанию '' Предупреждение System.Windows.Data: 89: BindingExpression (hash=54116930): TransferValue - использование окончательного значения ''
Проблема была в порядке инициализации MainWindow!
Итак, в момент, когда привязка была построена, мое свойство уровня 0 (SomeClassProp
) еще не был инициализирован, что привело к полному сбою привязки (по какой-то причине без выдачи предупреждения о бинге обычного уровня).
Короче говоря - трогательно SomeClassProp
инициализация перед InitializeComponent()
в MainWindow
конструктор сделал свое дело, привязка начала работать с ElementName
тоже:
public MainWindow()
{
SomeClassProp = new SomeClass();
InitializeComponent();
}
Ответ на вопрос - почему это работает с помощью RelativeSource
свойство - лежит в этих строках выходного журнала:
System.Windows.Data Warning: 66 : BindingExpression (hash=28713467): RelativeSource (FindAncestor) requires tree context
System.Windows.Data Warning: 65 : BindingExpression (hash=28713467): Resolve source deferred
Инициализация контекста данных с помощью RelativeSource
требует древовидного контекста и откладывается до некоторого момента времени после построения Window
(к тому времени SomeClassProperty
был уже инициализирован).