【问题标题】:Window DataContext or ElementName窗口 DataContext 或 ElementName
【发布时间】:2013-08-19 12:18:04
【问题描述】:

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

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

【问题讨论】:

  • 您能否具体说明在这种情况下“工作正常”和“失败”的含义?它不编译吗?它显示错误吗?它会抛出异常吗?它会使您的计算机崩溃吗?
  • @Default 工作正常 = 显示文本“Hello World!”在文本块中失败 = 不显示文本(保持为空)

标签: c# wpf xaml


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    {Binding} 默认总是指DataContext

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

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

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

    【讨论】:

      【解决方案3】:

      它在第一种和第二种情况下工作,因为TextBlock 能够找到HelloWorld 属性

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

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

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

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

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

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

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

      【讨论】:

      • 在第一种情况下,我没有指定 DataContext 那么它为什么要知道要得到什么?在第二种情况下,我没有指定它应该得到什么?如果你比较它们,在第一种情况下,窗口知道它有什么 DataContext,所以它不会在没有 ElementName 的情况下将它继承到 TextBlock,但是当我明确地说 DataContext 是什么时——它可以在不需要 ElementName 的情况下正确继承 DataContext。
      • ElementName 没有设置 DataContext,它只是改变了 Binding Source。
      【解决方案4】:

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

      public TestWindow()
      {
          InitializeComponent();
      
          this.DataContext = this;
      }
      

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

      【讨论】:

      • 第一个方法也没有指定DataContext,为什么会起作用?
      • 因为你告诉它不要使用DataContext,带有elementName
      • @RandRandom,因为当您抓取 Window 元素时,您正在指定要从中提取它的源。有了这个,WPF 数据绑定引擎可以在该元素上查找路径 HelloWorld
      猜你喜欢
      • 2013-11-07
      • 1970-01-01
      • 1970-01-01
      • 2016-03-08
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多