Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between setting DataContext=this in constructor and Binding to {RelativeSource Self} in WPF?

Next code works as expected:

AskWindow.xaml:

<Window
    x:Class='AskWPF.AskWindow'
    xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
    xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
    >

<DataGrid ItemsSource="{Binding SimpleItems}" />

</Window>

AskWindow.xaml.cs:

namespace AskWPF {

public class SimpleRow {
    private string firstColumn;
    private string secondColumn;

    public SimpleRow(string first, string second) {
        firstColumn = first;
        secondColumn = second;
    }

    public string FirstColumn {
        get { return firstColumn; }
        set { firstColumn = value; }
    }

    public string SecondColumn {
        get { return secondColumn; }
        set { secondColumn = value; }
    }
}

public partial class AskWindow : Window {

    private ObservableCollection<SimpleRow> simpleItems;

    public AskWindow() {
        InitializeComponent();
        DataContext = this;

        simpleItems = new ObservableCollection<SimpleRow>();
        simpleItems.Add(new SimpleRow("row 0, column 0", "row 0, column 1"));
        simpleItems.Add(new SimpleRow("row 1, column 0", "row 1, column 1"));
    }

    public ObservableCollection<SimpleRow> SimpleItems {
        get { return simpleItems; }
    }
}

}

But if set DataContext='{Binding RelativeSource={RelativeSource Self}}' in Window tag and comment line DataContext=this we get an empty window. Why?

AskWindow.xaml:

<Window .... DataContext='{Binding RelativeSource={RelativeSource Self}}'>

    <DataGrid ItemsSource="{Binding SimpleItems}" />

</Window>

AskWindow.xaml.cs:

...
public AskWindow() {
    InitializeComponent();
    // DataContext = this;

    simpleItems = new ObservableCollection<SimpleRow>();
    simpleItems.Add(new SimpleRow("row 0, column 0", "row 0, column 1"));
    simpleItems.Add(new SimpleRow("row 1, column 0", "row 1, column 1"));
}
...
like image 832
andrey_t Avatar asked Nov 02 '22 15:11

andrey_t


1 Answers

Here is my guess. In both cases at one point your Collection is null. To be precise right after InitializeComponent. At this point the initial databinding got the data, but no datacontext. Now by setting the DataContext your property gets raised and every binding related to it, gets invalidated and refreshed. Here is my guessing part, the reason it works is that the binding to the ItemsSource is deferred therefore it works to just set the collection in the next line.

So in short: Setting the Datacontext will retrigger the binding. But in your RelativeSource example your binding worked from the beginning but the collection was null and you never told wpf to refetch the binding. If you directly initialize your collection it should work fine.

like image 91
dowhilefor Avatar answered Nov 15 '22 06:11

dowhilefor