Что именно делает “RelativeSource FindAncestor” привязки данных WPF?

StackOverflow https://stackoverflow.com/questions/1636807

Вопрос

В настоящее время я работаю с пользовательским элементом управления WPF (корневым элементом моего файла XAML является "UserControl"), который, как я знаю, размещается внутри окна.Как я могу получить доступ к свойству окна, используя привязку данных?

Кто-нибудь знает, почему просто

<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}" Path="..." />

не работает?Сообщение об ошибке, которое я получаю, выглядит следующим образом:

Система.Windows.Предупреждение о данных:4 :Не удается найти источник для привязки со ссылкой 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1".

Редактировать: В итоге я использовал вариацию подхода ArsenMkrt, поэтому принял его ответ.Тем не менее, мне все еще интересно выяснить, почему FindAncestor не "просто работает".

Это было полезно?

Решение

Лучший способ - присвоить имя UserControl

Создайте свойство зависимостей MyProperty в UserControl с двухсторонним связыванием и свяжите его в главном окне, а затем привяжите в UserControl следующим образом

<UserControl x:Name = "myControl">
     <Label Content={Binding ElementName= myControl, Path=MyProperty}/>
</UserControl>

Другие советы

Если вы пытаетесь "сбежать" от ItemsControl или DataGridView чтобы добраться до Window возможно, вы обнаруживаете, что AncestorType of x:Type Window не работает.Или, по крайней мере, так кажется...

Если это так, то вы, вероятно, используете Blend или Visual Studio и ожидаете, что данные будут видны во время разработки, чего не произойдет, потому что оба VS + Blend создают свои собственные экземпляры, которые на самом деле не являются Windows.Это будет работать во время выполнения просто отлично, но не в режиме разработки.

Есть пара вещей, которые ты можешь сделать:

  • Оберните в UserControl

  • Вот альтернативное решение, которое я придумал.У этого есть одно преимущество в том, что вы не ссылаетесь на UserControl или Window напрямую, поэтому, если вы измените родительский контейнер, ваш код не сломается.

    <Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:views="clr-namespace:MyWPFApplication.Views"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                  
    x:Class="MyWPFApplication.Views.UPCLabelPrinterWindow"
    mc:Ignorable="d"
    x:Name="LayoutRoot"
    Title="UPCLabelPrinterWindow">
    
    <views:DataContextWrapper>
        <DockPanel>
            ...
        </DockPanel>
    </views:DataContextWrapper>
    

Где DataContextWrapper это просто Сетка

namespace MyWPFApplication.Views {
   public class DataContextWrapper : Grid
   {

   }
}

Затем, когда вы связываетесь, вы делаете это :

<TextBlock Text="{Binding="{Binding DataContext.SomeText, 
  RelativeSource={RelativeSource AncestorType={x:Type views:DataContextWrapper}, 
  Mode=FindAncestor}}" />

Примечание:если вы хотите привязаться к свойству В самом Window, это сложнее, и вам, вероятно, следует привязаться через свойство dependency или что-то в этом роде.Но если вы используете MVVM, то это одно из решений, которое я нашел.

Думаю, вам следует установить режим = " OneWayToSource " Вот так:

<TextBox Text="{Binding RelativeSource={RelativeSource FindAncestor ,AncestorType={x:Type Grid}},Path=BackGround , Mode=OneWayToSource , UpdateSourceTrigger = PropertyChanged}" />
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top