Программно создать привязку RelativeSource FindAncestor

Я пишу некоторый код, который программно создает привязки на лету, но я не могу прочитать значение, полученное в результате привязки, RelativeSourceMode которой установлен в FindAncestor. Мне было интересно, если кто-нибудь успешно создал привязку RelativeSource в коде (не XAML) с этим режимом?

При включенной трассировке Binding появляется предупреждение:

Предупреждение System.Windows.Data: 64: BindingExpression (hash=57957548): RelativeSource (FindAncestor) требует контекст дерева

Вот пример кода, который создает привязку RelativeSource:

 private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
 {
        // Create RelativeSource FindAncestor Binding
        var binding = new Binding
                             {
                                 RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ListBoxItem), 1),
                                 Path = new PropertyPath("Tag"),
                             };

        PresentationTraceSources.SetTraceLevel(binding, PresentationTraceLevel.High);
        BindingOperations.SetBinding(textBlock, TagProperty, binding);

        // Always null
        var findAncestorBindingResult = textBlock.Tag;

        // Create RelativeSource Self Binding
        binding = new Binding
        {
            RelativeSource = new RelativeSource(RelativeSourceMode.Self),
            Path = new PropertyPath("Text"),
        };

        PresentationTraceSources.SetTraceLevel(binding, PresentationTraceLevel.High);
        BindingOperations.SetBinding(textBlock, TagProperty, binding);

        // Has correct value Text property set from XAML
        var selfBindingResult = textBlock.Tag;
    }

А вот соответствующий XAML:

    <StackPanel>
        <ListBox x:Name="listBox">
            <ListBoxItem x:Name="listBoxItem" Tag="Item One" >
                <ListBoxItem.Content>
                    <TextBlock x:Name="textBlock">
                        <TextBlock.Text>
                            <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}" Path="Tag" />
                        </TextBlock.Text>
                    </TextBlock>
                </ListBoxItem.Content>
            </ListBoxItem>
        </ListBox>
        <Button Content="Debug" Click="ButtonBase_OnClick" />
    </StackPanel>

Дерево загружено, поэтому я мог смоделировать привязку FindAncestor (используя VisualTreeHelper.GetParent(...) чтобы найти целевой элемент привязки FindAncestor, а затем просто применить привязку RelativeSource Self к нему), но мне любопытно, почему это не работает.

Заранее спасибо!

1 ответ

Решение

Вы не можете получить значение привязанного свойства сразу после его связывания, вы в настоящее время блокируете UI-поток с помощью операции обработчика, привязка будет иметь место только после этого, когда поток простаивает (я думаю).

Вы должны удалить все после Always null прокомментируйте и проверьте значение позже, например, в обработчике другой кнопки. Кроме того, является ли связанный элемент на самом деле в дереве, как показано в XAML, только без привязки? Если нет, то это также объясняет такую ​​ошибку.

Изменить: Я только что заметил, что ваши привязки могут быть немного не так, они не переводятся в XAML, который вы опубликовали, как в XAML, который вы связываете Text и в своем коде вы устанавливаете привязку к TagProperty, Игнорируя, что связывание должно работать теоретически, просто обратите внимание, что сразу после установки привязки значение связанного свойства будет нулевым, как упоминалось ранее, поэтому не удаляйте его сразу (и связывайте TextProperty если вы хотите визуальные результаты).

Другие вопросы по тегам