简体   繁体   English

窗口DataContext或ElementName

[英]Window DataContext or ElementName

I am currently facing a little problem with specifing or not specifing the datacontext of a window, and why there is a difference between various methods. 我目前在指定或不指定窗口的数据上下文时遇到一个小问题,以及为什么各种方法之间存在差异。 Hope you can help me out. 希望你能帮助我。

Lets start with some code to show my problem. 让我们从一些代码开始展示我的问题。 This is the code behind for my TestWindow.xaml.cs, nothing really special about it just a simple string property 这是我的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();
    }
}

This code will be the same for all 3 following XAML layouts, so no changes behind the code only in XAML. 对于以下所有三个XAML布局,此代码都是相同的,因此仅在XAML中不会对代码进行任何更改。

1.) Databinding with given ElementName 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.) Databinding with specifing DataContext on Window 2.)在窗口上指定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.) Neither ElementName nor specifing DataContext 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>

The first two methods work just fine, but why fails the 3rd? 前两种方法可以正常工作,但是第三种方法为什么会失败?

In the first method I am not specifing the DataContext and it works automatically, in the second method I am not specifing the ElementName and it works, but without declaring one of those it fails. 在第一种方法中,我没有指定DataContext并自动运行,在第二种方法中,我没有指定ElementName并可以工作,但是没有声明其中一个失败。 Why would it fail getting both automatically, but work fine with getting each individually? 为什么不能同时自动获得它们,却可以很好地将它们单独获得呢?

Read the Remarks for the Binding.Source property . 阅读Binding.Source属性的备注。 The binding source is the object on which to look up the property specified by Path (HelloWorld). 绑定源是要在其上查找Path (HelloWorld)指定的属性的对象。 ElementName , RelativeSource , and Source set the binding source. ElementNameRelativeSourceSource设置绑定源。 If they are null, the source is the DataContext of the element that you are binding (TextBlock). 如果它们为null,则源是要绑定的元素(TextBlock)的DataContext。 If an element's DataContext is not explicitly set, it's inherited from a containing element. 如果未显式设置元素的DataContext,则它将从包含元素继承。

In the first case, any DataContext is irrelevant to the TextBlock binding, because the source is being set explicitly through ElementName. 在第一种情况下,任何DataContext都与TextBlock绑定无关,因为源是通过ElementName显式设置的。

In the second case, a DataContext is necessary to specify a source because it is not being set explicitly through ElementName, RelativeSource, or Source. 在第二种情况下,必须使用DataContext来指定源,因为没有通过ElementName,RelativeSource或Source对其进行显式设置。 TextBlock's DataContext is not set, so Window's is inherited. 未设置TextBlock的DataContext,因此继承了Window的。

In the third case, there is no explicit source and no DataContext to inherit, so the source is null and binding fails. 在第三种情况下,没有显式源,也没有要继承的DataContext,因此源为null,绑定失败。 There is no default source. 没有默认来源。

It is working in 1st and 2nd case because TextBlock is able to find HelloWorld property 因为TextBlock能够找到HelloWorld属性,所以它在第一种和第二种情况下都有效

In 1st case you are specifying ElemtnName so TextBlock will refer to Window and search for property HelloWorld in Window class. 在第一种情况下,您指定ElemtnName因此TextBlock将引用Window并在Window类中搜索属性HelloWorld

In 2nd case you are specifying DataContext of Window so Textblock will inherit that and will look for HelloWorld property in DataContext ie again Window class 在第二种情况下,您指定Window的DataContext ,因此Textblock将继承它,并将在DataContext寻找HelloWorld属性,即再次是Window

In 3rd case you aren't specifying anything so TextBlock is unable to find HelloWorld property 在第3种情况下,您未指定任何内容,因此TextBlock无法找到HelloWorld属性

In 1st case I am not specifing a DataContext so why should it know what to get? 在第一种情况下,我没有指定DataContext,所以为什么它应该知道要得到什么?

When you are setting ElementName , TextBlock will try to find HelloWorld from that element 设置ElementNameTextBlock将尝试从该元素中找到HelloWorld

In 2nd case I am not specifing what it should get? 在第二种情况下,我没有指定应该得到什么?

You are setting the DataContext of it's parent that is Window so it automatically inherits that and you are telling it to extract HelloWorld property from DataContext 您正在设置其父项(即WindowDataContext ,因此它会自动继承它,并告诉它从DataContext提取HelloWorld属性。

{Binding} by default always refers to the DataContext . 默认情况下, {Binding}始终引用DataContext

In your first example you simply deactivate the default behavior by using elementName, this uses the element as source then. 在第一个示例中,您只需使用elementName停用默认行为,然后将元素用作源。

In your second example you explicitly change the DataContext to point at your Window. 在第二个示例中,您显式更改了DataContext以指向您的Window。

So in the last example the {Binding HelloWorld} tries to convert null into and Object with a HelloWorld property which fails. 因此,在最后一个示例中, {Binding HelloWorld}尝试将null转换为and,并使用HelloWorld属性失败。

The third fails because the DataContext is not inferred. 第三次失败,因为未推断出 DataContext If you wanted the third to work, you'd do something like this: 如果您想让第三个工作,请执行以下操作:

public TestWindow()
{
    InitializeComponent();

    this.DataContext = this;
}

It doesn't know anything about the path HelloWorld because it doesn't have a DataContext . 它不知道路径的任何 HelloWorld ,因为它不具有DataContext

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM