What exactly does WPF Data Binding's “RelativeSource FindAncestor” do?

℡╲_俬逩灬. 提交于 2019-11-29 02:38:46

问题


I am currently working within a WPF user control (the root element of my XAML file is "UserControl"), which I know is being hosted inside a Window. How can I access a property of the Window using data binding?

Does anyone know why simply

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

does not work? The error message I get is:

System.Windows.Data Warning: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''.

Edit: I ended up using a variation on ArsenMkrt's approach, so have accepted his answer. However, I am still interested in finding out why FindAncestor does not "just work".


回答1:


The best way is to give a name to UserControl

Create dependency property MyProperty in UserControl with two way binding and bind it in main Window, than bind in UserControl like this

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



回答2:


If you're trying to 'escape' from an ItemsControl or DataGridView to get to a Window you may be finding that AncestorType of x:Type Window doesn't work. Or at least doesn't seem to...

If this is the case you're probably running Blend or Visual Studio and expecting the data to be visible at design time - which it won't because VS + Blend both create their own instances that aren't really Windows. It will work at runtime just fine, but not during design mode.

There's a couple things you can do:

  • Wrap in a UserControl

  • Here's an alternative solution I've come up with. It has one advantage in that you're not referencing a UserControl or Window directly, so if you change the parent container your code won't break.

    <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>
    

Where DataContextWrapper is just a Grid

namespace MyWPFApplication.Views {
   public class DataContextWrapper : Grid
   {

   }
}

Then when you bind you do this :

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

Note: if you want to bind to a property ON Window itself it's trickier and you should probably bind via a dependency property or something like that. But if you are using MVVM then this is one solution I found.




回答3:


I Think You Should SET Mode="OneWayToSource" Like this:

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


来源:https://stackoverflow.com/questions/1636807/what-exactly-does-wpf-data-bindings-relativesource-findancestor-do

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!