与相关源绑定
Binding with relative source
我正在尝试了解 RelativeSource
的工作原理。
通过下面的设置,我希望在窗体上看到文本“我是 MainViewModel”,但是我在调试器中看到一个错误,MainWindow
:
Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='UnderstandingBindings.ViewModels.MainViewModel', AncestorLevel='1''. BindingExpression:Path=SomeProperty; DataItem=null; target element is 'TextBlock' (Name='myText'); target property is 'Text' (type 'String')
我有一个这样的 ViewModel:
class MainViewModel
{
public string SomeProperty { get => "I am the MainViewModel"; }
private readonly ChildViewModel _child = new ChildViewModel();
public ChildViewModel Child => _child;
}
class ChildViewModel
{
public string SomeProperty { get => "I am the ChildViewModel"; }
}
主窗口 XAML 看起来像:
<Window x:Class="UnderstandingBindings.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:UnderstandingBindings.Views"
xmlns:vm="clr-namespace:UnderstandingBindings.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel x:Name="pnlMain">
<TextBlock x:Name="myText" Text="{Binding SomeProperty, RelativeSource={RelativeSource AncestorType={x:Type vm:MainViewModel}}}"/>
</StackPanel>
</Window>
数据上下文分配如下:
public partial class MainWindow : Window
{
private readonly MainViewModel _viewModel = new MainViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = _viewModel.Child;
}
}
wpf 查找声明绑定的 xaml 元素的祖先。你可以把它想象成沿着视觉树向上走。
您可以使用它来绑定到那个 Ancestor 上的 属性,或者必须通过它的 DataContext 属性 绑定到视图模型。例如:
<TextBlock x:Name="myText" Text="{Binding DataContext.Child.SomeProperty, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
只有在您的示例中将 DataContext 设置为 MainViewModel 时才有效。如果您希望 Binding 朝着您期望的方向发展,那么您需要在 Child 上添加对 Parent Viewmodel 的引用。
relative source within a binding 的声明执行以下操作。
Gets or sets the binding source by specifying its location relative to the position of the binding target.
这意味着它将绑定的 Source
属性 设置为可视化树中的元素。这可以是当前元素 (Self
) 或祖先元素(例如 StackPanel
是它包含的 TextBlock
的祖先元素)或在控件模板的情况下是模板化的父元素。这取决于您设置的 Mode
。相对源允许您在绑定中的该元素上指定 属性 路径,例如它的 DataContext
或 Tag
或任何其他 属性.
您得到的错误转换为:我在从 TextBlock
开始的可视化树中搜索类型 MainViewModel
的实例。然后我检查了下一个祖先StackPanel
,它不是MainViewModel
。然后我检查了下一个祖先Window
,它也不是MainViewModel
。没有其他祖先,所以我找不到任何东西。
您在这里滥用相对来源。视图模型不是可视化树的一部分,而是充当元素的数据上下文。对于您使用数据上下文的示例,正确的方法就足够了。一旦你在 MainWindow
上设置数据上下文,它在所有子控件中都是 inherited,如果没有另外指定,例如在元素上显式分配不同的数据上下文。因此,MainWindow
的子项 TextBlock
将获得您分配给 MainWindow
.[=46 的 DataContext
属性 的相同数据上下文=]
您的示例中的数据上下文是 ChildViewModel
的一个实例,因此为了绑定到它的 SomeProperty
,您不需要相对源绑定,只需一个 属性使用相应控件的DataContext
(设置为绑定源)自动解析的路径。
<TextBlock x:Name="myText" Text="{Binding SomeProperty}"/>
这将导致以下文本:我是 ChildViewModel
如果你想绑定到MainViewModel
的SomeProperty
,你应该相应地设置DataContext
。
public MainWindow()
{
InitializeComponent();
this.DataContext = _viewModel;
}
TextBlock
中的绑定同上,如果要显示MainViewModel
的SomeProperty
。
<TextBlock x:Name="myText" Text="{Binding SomeProperty}"/>
如果您想绑定 ChildViewModel
的 SomeProperty
,您可以更改路径。
<TextBlock x:Name="myText" Text="{Binding Child.SomeProperty}"/>
在这两个示例中,它都会导致以下文本:I am the MainViewModel
我正在尝试了解 RelativeSource
的工作原理。
通过下面的设置,我希望在窗体上看到文本“我是 MainViewModel”,但是我在调试器中看到一个错误,MainWindow
:
Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='UnderstandingBindings.ViewModels.MainViewModel', AncestorLevel='1''. BindingExpression:Path=SomeProperty; DataItem=null; target element is 'TextBlock' (Name='myText'); target property is 'Text' (type 'String')
我有一个这样的 ViewModel:
class MainViewModel
{
public string SomeProperty { get => "I am the MainViewModel"; }
private readonly ChildViewModel _child = new ChildViewModel();
public ChildViewModel Child => _child;
}
class ChildViewModel
{
public string SomeProperty { get => "I am the ChildViewModel"; }
}
主窗口 XAML 看起来像:
<Window x:Class="UnderstandingBindings.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:UnderstandingBindings.Views"
xmlns:vm="clr-namespace:UnderstandingBindings.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel x:Name="pnlMain">
<TextBlock x:Name="myText" Text="{Binding SomeProperty, RelativeSource={RelativeSource AncestorType={x:Type vm:MainViewModel}}}"/>
</StackPanel>
</Window>
数据上下文分配如下:
public partial class MainWindow : Window
{
private readonly MainViewModel _viewModel = new MainViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = _viewModel.Child;
}
}
wpf 查找声明绑定的 xaml 元素的祖先。你可以把它想象成沿着视觉树向上走。
您可以使用它来绑定到那个 Ancestor 上的 属性,或者必须通过它的 DataContext 属性 绑定到视图模型。例如:
<TextBlock x:Name="myText" Text="{Binding DataContext.Child.SomeProperty, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
只有在您的示例中将 DataContext 设置为 MainViewModel 时才有效。如果您希望 Binding 朝着您期望的方向发展,那么您需要在 Child 上添加对 Parent Viewmodel 的引用。
relative source within a binding 的声明执行以下操作。
Gets or sets the binding source by specifying its location relative to the position of the binding target.
这意味着它将绑定的 Source
属性 设置为可视化树中的元素。这可以是当前元素 (Self
) 或祖先元素(例如 StackPanel
是它包含的 TextBlock
的祖先元素)或在控件模板的情况下是模板化的父元素。这取决于您设置的 Mode
。相对源允许您在绑定中的该元素上指定 属性 路径,例如它的 DataContext
或 Tag
或任何其他 属性.
您得到的错误转换为:我在从 TextBlock
开始的可视化树中搜索类型 MainViewModel
的实例。然后我检查了下一个祖先StackPanel
,它不是MainViewModel
。然后我检查了下一个祖先Window
,它也不是MainViewModel
。没有其他祖先,所以我找不到任何东西。
您在这里滥用相对来源。视图模型不是可视化树的一部分,而是充当元素的数据上下文。对于您使用数据上下文的示例,正确的方法就足够了。一旦你在 MainWindow
上设置数据上下文,它在所有子控件中都是 inherited,如果没有另外指定,例如在元素上显式分配不同的数据上下文。因此,MainWindow
的子项 TextBlock
将获得您分配给 MainWindow
.[=46 的 DataContext
属性 的相同数据上下文=]
您的示例中的数据上下文是 ChildViewModel
的一个实例,因此为了绑定到它的 SomeProperty
,您不需要相对源绑定,只需一个 属性使用相应控件的DataContext
(设置为绑定源)自动解析的路径。
<TextBlock x:Name="myText" Text="{Binding SomeProperty}"/>
这将导致以下文本:我是 ChildViewModel
如果你想绑定到MainViewModel
的SomeProperty
,你应该相应地设置DataContext
。
public MainWindow()
{
InitializeComponent();
this.DataContext = _viewModel;
}
TextBlock
中的绑定同上,如果要显示MainViewModel
的SomeProperty
。
<TextBlock x:Name="myText" Text="{Binding SomeProperty}"/>
如果您想绑定 ChildViewModel
的 SomeProperty
,您可以更改路径。
<TextBlock x:Name="myText" Text="{Binding Child.SomeProperty}"/>
在这两个示例中,它都会导致以下文本:I am the MainViewModel