我目前在指定或不指定窗口的datacontext时面临一个小问题,以及为什么各种方法之间存在差异。希望你能帮助我。
让我们从一些代码开始,以显示我的问题。这是我的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>
前两种方法工作正常,但为什么第3次失败?
在第一种方法中,我没有指定DataContext并且它自动工作,在第二种方法中,我没有指定ElementName并且它可以工作,但是没有声明其中一个失败。为什么它会自动失败,但是单独获取每个都可以正常工作?
答案 0 :(得分:2)
阅读Binding.Source property的备注。绑定源是查找Path
(HelloWorld)指定的属性的对象。 ElementName
,RelativeSource
和Source
设置绑定源。如果它们为null,则源是您要绑定的元素的DataContext(TextBlock)。如果未显式设置元素的DataContext,则它继承自包含元素。
在第一种情况下,任何DataContext都与TextBlock绑定无关,因为源是通过ElementName显式设置的。
在第二种情况下,需要DataContext来指定源,因为它没有通过ElementName,RelativeSource或Source显式设置。未设置TextBlock的DataContext,因此继承了Window。
在第三种情况下,没有显式的源和没有DataContext可以继承,因此源为null并且绑定失败。没有默认来源。
答案 1 :(得分:1)
它正在第1和第2种情况下工作,因为TextBlock
能够找到HelloWorld
属性
在第一种情况下,您指定了ElemtnName
,因此TextBlock
将引用Window
并在Window类中搜索属性HelloWorld
。
在第二种情况下,您指定了DataContext
的窗口,因此Textblock
将继承该窗口并在HelloWorld
中查找DataContext
属性,即Window
类< / p>
在第三种情况下,您没有指定任何内容,因此TextBlock无法找到HelloWorld
属性
在第一种情况下,我没有指定DataContext,为什么它应该知道 该怎么办?
当您设置ElementName
时,TextBlock
会尝试从该元素中找到HelloWorld
在第二种情况下,我没有说明它应该得到什么?
您正在设置DataContext
的父Window
,因此它会自动继承该内容,并且您告诉它从HelloWorld
中提取DataContext
属性
答案 2 :(得分:1)
{Binding}
始终引用DataContext
。
在第一个示例中,您只需使用elementName停用默认行为,然后使用该元素作为源。
在第二个示例中,您明确地将DataContext
更改为指向您的窗口。
因此,在最后一个示例中,{Binding HelloWorld}
尝试将null
转换为具有失败的HelloWorld属性的Object。
答案 3 :(得分:0)
第三个失败是因为DataContext
未被推断。如果你想让第三个工作,你会做这样的事情:
public TestWindow()
{
InitializeComponent();
this.DataContext = this;
}
它不知道关于路径HelloWorld
的任何,因为它没有DataContext
。