WPF Data Binding的"RelativeSource FindAncestor"究竟做了什么?

use*_*783 21 data-binding wpf xaml relativesource findancestor

我目前在WPF用户控件(我的XAML文件的根元素是"UserControl")中工作,我知道它是在Window中托管的.如何使用数据绑定访问Window的属性?

有谁知道为什么简单

<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}" Path="..." />
Run Code Online (Sandbox Code Playgroud)

不起作用?我得到的错误信息是:

System.Windows.Data警告:4:无法找到绑定源,引用'RelativeSource FindAncestor,AncestorType ='System.Windows.Window',AncestorLevel ='1''.

编辑:我最终使用了ArsenMkrt方法的变体,因此接受了他的回答.但是,我仍然有兴趣找出为什么FindAncestor不"正常工作".

Ars*_*yan 18

最好的方法是给UserControl命名

在UserControl中创建依赖属性MyProperty,使用双向绑定并在主窗口中绑定它,而不是在UserControl中绑定像这样

<UserControl x:Name = "myControl">
     <Label Content={Binding ElementName= myControl, Path=MyProperty}/>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

  • 你可以在UserControl中创建依赖属性吗?你不在窗口中添加usercontrol吗?<UserControl MyProperty = {...与窗口属性绑定} /> (2认同)
  • 我不知道为什么不诚实,但我的答案是更好的解决方案,因为在开发期间可以更改父类型 (2认同)

Sim*_*ver 5

如果您试图从 anItemsControlDataGridView到达 a 中“逃脱”,Window您可能会发现 AncestorTypex:Type Window不起作用。或者至少似乎没有……

如果是这种情况,您可能正在运行 Blend 或 Visual Studio 并期望数据在设计时可见 - 这不会,因为 VS + Blend 都创建了它们自己的实例,这些实例并不是真正的 Windows。它可以在运行时正常工作,但不能在设计模式下工作。

您可以做以下几件事:

  • 包装在用户控件中

  • 这是我想出的替代解决方案。它的一个优点是您没有直接引用 aUserControlWindow,因此如果您更改父容器,您的代码不会中断。

    <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>
    
    Run Code Online (Sandbox Code Playgroud)

哪里DataContextWrapper只是一个网格

namespace MyWPFApplication.Views {
   public class DataContextWrapper : Grid
   {

   }
}
Run Code Online (Sandbox Code Playgroud)

然后当你绑定你这样做:

<TextBlock Text="{Binding="{Binding DataContext.SomeText, 
  RelativeSource={RelativeSource AncestorType={x:Type views:DataContextWrapper}, 
  Mode=FindAncestor}}" />
Run Code Online (Sandbox Code Playgroud)

注意:如果你想绑定到一个属性 ON Window 本身就比较棘手,你可能应该通过依赖属性或类似的东西进行绑定。但是,如果您使用的是 MVVM,那么这是我找到的一种解决方案。