Что именно делает “RelativeSource FindAncestor” привязки данных WPF?
-
06-07-2019 - |
Вопрос
В настоящее время я работаю с пользовательским элементом управления 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}" />