Программно создать привязку RelativeSource FindAncestor - PullRequest
0 голосов
/ 16 сентября 2011

Я пишу некоторый код, который программно создает привязки на лету, но я не могу прочитать значение, полученное в результате привязки, 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 Ответ

1 голос
/ 16 сентября 2011

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

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

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

...