Подтвердить что ты не робот

Почему привязка файла данных MainWindow в XAML не может действовать так же, как привязка в коде с этим. Datacontext = this?

Я пытаюсь использовать привязку данных для привязки ObservableCollection к ItemsSource DataGrid, так как я узнаю о WPF и т.д.

В кодировке я могу установить DataContext с this.DataContext = this; или bloopDataGrid.DataContext = this;. Это прекрасный и денди.

Я думал, что могу попробовать что-то вроде

<Window.DataContext>
    <local:MainWindow/>
</Window.DataContext>

в моем главном окне, но это вызывает исключение, как описано в этом вопросе. Хорошо, это имеет смысл.

После прочтения этого и других вопросов/ответов, которые говорят попробовать 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>

Что тоже не работает. Возможно, не по той же причине, но я не могу понять проблему с этим.

Как ни странно, я не могу воспроизвести пример перезаписи, показанный в Rachel Lim blog post.

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>

С#

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; }
        }

    }
}

Вышеприведенный код - это то, что я использую для проверки этого, и в настоящее время использует версию кода, которая правильно дает мне

In codebehind

Что я делаю неправильно, что мешает мне получать те же результаты, что и выше, но с помощью XAML для обработки DataContext? Не подключаю ли я точки правильно?... я пропущу несколько точек?

4b9b3361

Ответ 1

<Window.DataContext>
    <local:MainWindow/>
</Window.DataContext>

не совпадает с

this.DataContext = this;

Первый создает новый экземпляр класса MainWindow и присваивает его свойству DataContext Window, а второй назначает тот же самый экземпляр Window его DataContext.

Чтобы добиться этого в XAML, вам необходимо использовать привязку RelativeSource:

<Window DataContext="{Binding RelativeSource={RelativeSource Self}}">
</Window>

Edit:

Разница в поведении между определением DataContext в XAML и позади кода вызвана тем фактом, что XAML фактически анализируется, когда конструктор заканчивает выполнение, потому что Dispatcher ожидает код пользователя (в конструкторе окна) для завершения перед выполнением своих ожидающих операций.

Это приводит к тому, что фактические значения свойств различаются в эти разные моменты, и поскольку нет INotifyPropertyChanged, WPF не имеет возможности обновлять пользовательский интерфейс, чтобы отражать новые значения.

Вы could реализуете INotifyPropertyChanged в самом Window, но я предлагаю создать ViewModel для этого, так как мне не нравится факт смешивания INotifyPropertyChanged (который больше представляет собой концепцию ViewModel) с DependencyObject -пределенные классы (элементы интерфейса).