1

我目前在指定或不指定窗口的数据上下文方面遇到一个小问题,以及为什么各种方法之间存在差异。希望你能帮助我。

让我们从一些代码开始来展示我的问题。这是我的 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 并且它可以工作,但没有声明其中一个失败。为什么它不能自动获得两者,但单独获得每个都可以正常工作?

4

4 回答 4

2

{Binding}默认情况下总是指DataContext.

在您的第一个示例中,您只需使用 elementName 停用默认行为,然后使用元素作为源。

在您的第二个示例中,您明确更改DataContext指向您的窗口。

因此,在最后一个示例中,{Binding HelloWorld}尝试将null带有 HelloWorld 属性的 Object 转换为失败。

于 2013-08-19T12:25:14.377 回答
2

阅读Binding.Source 属性的备注。绑定源是要在其上查找由Path(HelloWorld) 指定的属性的对象。ElementName, RelativeSource, 并Source设置绑定源。如果它们为空,则源是您正在绑定的元素的 DataContext (TextBlock)。如果一个元素的 DataContext 没有被显式设置,它是从一个包含的元素继承而来的。

在第一种情况下,任何 DataContext 都与 TextBlock 绑定无关,因为源是通过 ElementName 显式设置的。

在第二种情况下,必须使用 DataContext 来指定源,因为它没有通过 ElementName、RelativeSource 或 Source 显式设置。TextBlock 的 DataContext 没有设置,所以继承了 Window 的。

第三种情况,没有显式源,也没有DataContext可以继承,所以源为空,绑定失败。没有默认来源。

于 2013-08-19T12:51:32.103 回答
1

它适用于第一种和第二种情况,因为TextBlock能够找到HelloWorld财产

在第一种情况下,您要指定ElemtnName因此TextBlock将引用Window并搜索HelloWorldWindow 类中的属性。

在第二种情况下,您指定DataContext了 Window ,因此Textblock将继承它并再次在 ie类中查找HelloWorld属性DataContextWindow

在第三种情况下,您没有指定任何内容,因此 TextBlock 无法找到HelloWorld属性

在第一种情况下,我没有指定 DataContext 那么它为什么要知道要得到什么?

当您设置ElementName时,TextBlock将尝试HelloWorld从该元素中查找

在第二种情况下,我没有指定它应该得到什么?

您正在设置DataContext它的父级,Window因此它会自动继承它,并且您告诉它从中提取HelloWorld属性DataContext

于 2013-08-19T12:21:44.927 回答
0

第三个失败,因为DataContext没有推断出来。如果你想让第三个工作,你会做这样的事情:

public TestWindow()
{
    InitializeComponent();

    this.DataContext = this;
}

它对路径一无所知,因为HelloWorld它没有DataContext.

于 2013-08-19T12:20:19.457 回答