Что именно делает "RelativeSource FindAncestor" WPF Data Binding?
В настоящее время я работаю в пользовательском элементе управления 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 не "просто работает".
3 ответа
Лучший способ - дать имя UserControl
Создайте свойство зависимостей MyProperty в UserControl с двухсторонним связыванием и привяжите его в главном окне, чем связать в UserControl следующим образом
<UserControl x:Name = "myControl">
<Label Content={Binding ElementName= myControl, Path=MyProperty}/>
</UserControl>
Если вы пытаетесь "сбежать" от 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}}" />
Примечание: если вы хотите привязать свойство к самому окну, это сложнее, и вам, вероятно, следует выполнить привязку через свойство зависимости или что-то в этом роде. Но если вы используете MVVM, то это единственное решение, которое я нашел.
Если вы используете модель представления в качестве DataContext вашего окна, а свойство, к которому вам нужно привязаться, относится к этой модели представления, тогда вы должны префикс пути с DataContext.MyPropertyPath, примерно так:
<TextBox Text="{Binding DataContext.MyProperty, RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}"/>
это переводится как "Найдите мне окно предка, а затем посмотрите в его контексте данных на MyProperty".
Я думаю, что вы должны SET Mode="OneWayToSource" Вот так:
<TextBox Text="{Binding RelativeSource={RelativeSource FindAncestor ,AncestorType={x:Type Grid}},Path=BackGround , Mode=OneWayToSource , UpdateSourceTrigger = PropertyChanged}" />