Window DataContext or ElementName
本文关键字:ElementName or DataContext Window | 更新日期: 2023-09-27 18:28:07
我目前在指定或不指定窗口的数据上下文方面遇到了一个小问题,以及为什么各种方法之间存在差异。希望你能帮我。
让我们从一些代码开始展示我的问题。这是我的TestWindow.xaml.cs的代码,没有什么特别的,只是一个简单的字符串属性
public partial class TestWindow : Window
{
private string _helloWorld = "Hello World!";
public string HelloWorld
{
get { return _helloWorld; }
set { _helloWorld = value; }
}
public TestWindow()
{
InitializeComponent();
}
}
此代码对于以下3个XAML布局都是相同的,因此仅在XAML中代码后面没有任何更改。
1.)具有给定ElementName 的数据绑定
<Window x:Class="Ktsw.Conx.ConxClient.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300"
Name="TestWin">
<Grid>
<TextBlock Text="{Binding HelloWorld, ElementName=TestWin}"></TextBlock>
</Grid>
</Window>
2.)在Window 上指定DataContext的数据绑定
<Window x:Class="Ktsw.Conx.ConxClient.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<TextBlock Text="{Binding HelloWorld}"></TextBlock>
</Grid>
</Window>
3.)既没有ElementName也没有指定DataContext
<Window x:Class="Ktsw.Conx.ConxClient.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300">
<Grid>
<TextBlock Text="{Binding HelloWorld}"></TextBlock>
</Grid>
</Window>
前两种方法效果不错,但为什么第三种方法失败了?
在第一个方法中,我没有指定DataContext,它自动工作,在第二个方法中我没有指定ElementName,它工作,但没有声明其中一个,它失败了。为什么它不能自动获得两者,但单独获得两者都很好?
阅读Binding.Source属性的备注。绑定源是要在其上查找Path
(HelloWorld)指定的属性的对象。ElementName
、RelativeSource
和Source
设置绑定源。如果它们为null,则源为要绑定的元素(TextBlock)的DataContext。如果没有显式设置元素的DataContext,则它是从包含元素继承的。
在第一种情况下,任何DataContext都与TextBlock绑定无关,因为源是通过ElementName显式设置的。
在第二种情况下,指定源需要DataContext,因为它不是通过ElementName、RelativeSource或source显式设置的。未设置TextBlock的DataContext,因此继承了Window的。
在第三种情况下,没有显式源,也没有要继承的DataContext,因此源为null,绑定失败。没有默认来源。
{Binding}
总是指DataContext
。
在第一个示例中,您只需使用elementName来停用默认行为,然后将该元素用作源。
在第二个示例中,您明确地将DataContext
更改为指向您的Window。
因此,在最后一个示例中,{Binding HelloWorld}
尝试将null
转换为具有HelloWorld属性的对象,但失败了。
它在第一种和第二种情况下都有效,因为TextBlock
能够找到HelloWorld
属性
在第一种情况下,您指定的是ElemtnName
,因此TextBlock
将引用Window
并在Window类中搜索属性HelloWorld
。
在第二种情况下,您正在指定Window的DataContext
,因此Textblock
将继承该属性,并在DataContext
中查找HelloWorld
属性,即再次查找Window
类
在第三种情况下,您没有指定任何内容,因此TextBlock无法找到HelloWorld
属性
在第一种情况下,我没有指定DataContext,为什么它应该知道得到什么?
当您设置ElementName
时,TextBlock
将尝试从元素中查找HelloWorld
在第二种情况下,我没有具体说明它应该得到什么?
您正在设置它的父级DataContext
,即Window
,以便它自动继承它,并告诉它从DataContext
中提取HelloWorld
属性
第三个失败,因为DataContext
不是推断的如果你想让第三个工作,你可以这样做:
public TestWindow()
{
InitializeComponent();
this.DataContext = this;
}
它对路径HelloWorld
一无所知,因为它没有DataContext
。