为什么在XAML中绑定MainWindow datacontext失败的行为与使用this.datacontext = this的代码隐藏中的绑定相同?

Hyd*_*ium 13 c# data-binding wpf xaml

我正在尝试使用Data绑定将ObservableCollection绑定到DataGrid的ItemsSource,因为我了解了WPF和其他内容.

在代码隐藏中,我可以使用this.DataContext = this;或设置DataContext bloopDataGrid.DataContext = this;.这很好,花花公子.

我以为我可以尝试类似的东西

<Window.DataContext>
    <local:MainWindow/>
</Window.DataContext>
Run Code Online (Sandbox Code Playgroud)

在我的主窗口中,但这会导致Stack Overflow异常,如本问题中所述.很好,这是有道理的.

在阅读了这个以及DataContext="{Binding RelativeSource={RelativeSource Self}}"在窗口的XAML代码中尝试的其他问题/答案之后,我想我实际上可以做到这一点.显然我做不到.或者至少,IDE让我和它的语法正确,但不做我想要的(即,究竟是什么this.DataContext = this;).

然后我读到关于使用的内容,"{Binding ElementName=, Path=}"并试图像这样使用它:

<DataGrid
    Name="bloopDataGrid"
    Grid.Row="1"
    ItemsSource="{Binding ElementName=testWin, Path=OutputCollection}">
</DataGrid>
Run Code Online (Sandbox Code Playgroud)

哪个也行不通.也许不是出于同样的原因,但我无法弄清楚它的问题.

奇怪的是,我无法复制Rachel Lim博客文章中显示的重新绑定示例.

XAML:

<Window
    x:Class="DataBinding.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow"
    Height="350"
    Width="525"
    x:Name="testWin">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <Label Grid.Row="0" Content="{Binding text}">   
        </Label>

        <DataGrid
            Name="bloopDataGrid"
            Grid.Row="1"
            ItemsSource="{Binding Path=OutputCollection}">
        </DataGrid>
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

C#:

using System;
using System.Collections.ObjectModel; //For ObservableCollection<T>
using System.Windows;

namespace DataBinding
{
    public partial class MainWindow : Window
    {
        public String text { get; set; }
        public ObservableCollection<testStruct> OutputCollection { get; set; }

        public struct testStruct
        {
            public testStruct(String x, String y) : this()
            {
                Col1 = x;
                Col2 = y;
            }
            public String Col1 { get; set; }
            public String Col2 { get; set; }
        }

        public MainWindow()
        {
            InitializeComponent();

            testA t1 = new testA();
            this.DataContext = this;
            //this.DataContext = t1;
            //bloopDataGrid.DataContext = this;
            text = "bound \"this\"";
            t1.text = "bound a class";

            OutputCollection = new ObservableCollection<testStruct>();
            OutputCollection.Add(new testStruct("1", "2"));
            OutputCollection.Add(new testStruct("3", "4"));
        }

        public class testA
        {
            public String text { get; set; }
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码是我用来测试它的,目前正在使用正确给我的代码隐藏版本

在代码隐藏中

我做错了什么,这使我无法获得与上图相同的结果,但是使用XAML进行DataContext处理?我没有正确连接点吗?......我错过了一些点吗?

Fed*_*gui 31

<Window.DataContext>
    <local:MainWindow/>
</Window.DataContext>
Run Code Online (Sandbox Code Playgroud)

是不一样的

this.DataContext = this;
Run Code Online (Sandbox Code Playgroud)

第一个是创建类的新实例MainWindow并将其分配给的DataContext属性Window,而第二个是将相同的实例分配Window给它的DataContext属性.

为了在XAML中实现这一点,您需要使用RelativeSource绑定:

<Window DataContext="{Binding RelativeSource={RelativeSource Self}}">
</Window>
Run Code Online (Sandbox Code Playgroud)

编辑:

定义之间的行为差异DataContext在XAML和代码背后的事实造成的,当构造函数执行完毕XAML实际上解析,因为Dispatcher用户代码等待(在窗口的构造函数)来执行前完成其待处理的操作

这导致实际属性值在这些不同时刻不同,并且由于没有INotifyPropertyChanged,WPF无法更新UI以反映新值.

你在它自己could实现,但我建议为此创建一个ViewModel,因为我不喜欢混合(更像是一个ViewModel概念)与-derived类(UI元素)的事实.INotifyPropertyChangedWindowINotifyPropertyChangedDependencyObject