Подтвердить что ты не робот

Что именно делает WPF Data Binding "RelativeSource FindAncestor"?

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

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

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

не работает? Сообщение об ошибке, которое я получаю:

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

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

4b9b3361

Ответ 1

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

Создать свойство зависимостей MyProperty в UserControl с двухсторонней привязкой и привязать его в главном окне, чем привязать в UserControl, как это

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

Ответ 2

Если вы пытаетесь "сбежать" из ItemsControl или DataGridView, чтобы перейти к Window, вы можете обнаружить, что AncestorType 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}}" />

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

Ответ 3

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

<TextBox Text="{Binding RelativeSource={RelativeSource FindAncestor ,AncestorType={x:Type Grid}},Path=BackGround , Mode=OneWayToSource , UpdateSourceTrigger = PropertyChanged}" />