locked
Setting DataContext in XAML as in "Introduction to WPF" RRS feed

  • Question

  • I have written a few programs in XAML but the data binding is the most confusing. I want to start with the basics.

    See "Data Binding" in Introduction to WPF. The following is from it.

    class Person
        {
            string name = "No Name";
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
        }

    <TextBox Name="personNameTextBox" Text="{Binding Path=Name}" />

    public partial class DataBindingWindow : Window
        {
            public DataBindingWindow()
            {
                InitializeComponent();
                Person person = new Person();
                this.DataContext = person;
            }
        }

    My question is about the "this.DataContext = person" statement. What would be the easiest way to do the equivalent in XAML? I know it is possible to use Window.DataContext in XAML to create a new instance of the data in XAML but I want to know the equivalent of doing the binding in XAML that matches the code-behind in that example as closely as possible.

    I expect someone to say that the code does not use MVVM so it is no good and then show how to do the same thing using MVVM. I did not write the code, Microsoft did; I want to understand how it is done without MVVM.

    Perhaps there is no easy way to do it in XAML.



    Sam Hobbs
    SimpleSamples.Info


    • Edited by Simple Samples Saturday, July 2, 2016 8:12 AM formatting only
    • Changed type DotNet Wang Sunday, July 24, 2016 7:25 AM
    • Changed type Simple Samples Sunday, July 24, 2016 7:42 AM This is a cleary-defined question but not so easy to answer
    Saturday, July 2, 2016 8:09 AM

Answers

  • The equivalent of the following C#:

    this.DataContext = person;

    Would be the following XAML in the Window tag:

    DataContext="{Binding Source=person}"

    However the DataContext attribute is not recognized in that manner. In that context, XAML recognizes "person" as being a string literal, not a variable (or whatever term you want to use instead of "variable"). Therefore there is no direct equivalent in XAML of the sample C# code.



    Sam Hobbs
    SimpleSamples.Info

    Sunday, July 24, 2016 8:51 AM

All replies

  • I think your answer has to do with resources and a resource dictionary. 

    http://stackoverflow.com/questions/16979502/can-not-bind-within-resource-dictionary

    but I do not know for sure because I find it much easier to setup the data context and binding in the code behind.  For the data context I do not set the data context of the Window. Instead I normally give the outer most container an x:name and then set the data context of that element to the model or window class. 

    As far as binding to the Person class it is best to have the class you bind to implement the INotifyPropertyChanged interface.  Then the properties in that class being bound to call the RaisePropertyChanged method in the setter of the property.

    Saturday, July 2, 2016 10:20 AM
  • >>What would be the easiest way to do the equivalent in XAML? I know it is possible to use Window.DataContext in XAML to create a new instance of the data in XAML but I want to know the equivalent of doing the binding in XAML that matches the code-behind in that example as closely as possible.

    The following markup creates an instance of the Person class and set the window's DataContext property to this instance:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApplication1"
            mc:Ignorable="d"
            Title="Window2" Height="300" Width="300">
        <Window.DataContext>
            <local:Person />
        </Window.DataContext>
    ...

    This is the XAML equivalent of creating an instance of an object and set the DataContext property programmatically:

    Person person = new Person();
    this.DataContext = person;

    XAML is markup language that is intended to be used to define the visual presentation of an application. It is not a programming language where you define variables.

    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    • Proposed as answer by issam1975 Sunday, July 3, 2016 3:18 AM
    Saturday, July 2, 2016 10:46 AM
  • I think your answer has to do with resources and a resource dictionary. 

    http://stackoverflow.com/questions/16979502/can-not-bind-within-resource-dictionary

    but I do not know for sure because I find it much easier to setup the data context and binding in the code behind.  For the data context I do not set the data context of the Window. Instead I normally give the outer most container an x:name and then set the data context of that element to the model or window class. 

    That article does not even show any code-behind. Most articles about XAML do not show the corresponding code-behind and that makes it difficult for me to learn about how to connect the two. The XAML in that article is also too complex, I am asking about a simple sample.

    As far as binding to the Person class it is best to have the class you bind to implement the INotifyPropertyChanged interface.  Then the properties in that class being bound to call the RaisePropertyChanged method in the setter of the property.

    This is just a simple example written by Microsoft. It is not intended to do everything. Discussing what it could do distracts the discussion and inhibits getting answers.



    Sam Hobbs
    SimpleSamples.Info

    Saturday, July 2, 2016 11:22 AM
  • The following markup creates an instance of the Person class and set the window's DataContext property to this instance:

    I said I know it is possible to use Window.DataContext. My intent was to explicitly exclude that. I want to know how to do it, excluding that way.

    This is the XAML equivalent of creating an instance of an object and set the DataContext property programmatically:

    Person person = new Person();
    this.DataContext = person;

    "XAML equivalent" means how to do it in XAML. My question has "this.DataContext = person" in C# and I am asking how to do the equivalent in XAML (in other words, not the equivalent of XAML).

    XAML is markup language that is intended to be used to define the visual presentation of an application. It is not a programming language where you define variables.

    I am sorry, but discussion of the theory of XAML will distract from this discussion.

    Assuming it is true that we do not want to declare variables in XAML, we do not want to use Window.DataContext or any use of DataContext like that in XAML.



    Sam Hobbs
    SimpleSamples.Info

    Saturday, July 2, 2016 11:46 AM
  • >>I said I know it is possible to use Window.DataContext. My intent was to explicitly exclude that. I want to know how to do it, excluding that way.

    There is no other way...This is the only way of setting the DataContext property in the XAML markup. It is called property element syntax: https://msdn.microsoft.com/en-us/library/ms788723(v=vs.100).aspx#property_element_syntax

    >>>>My question has "this.DataContext = person" in C# and I am asking how to do the equivalent in XAML (in other words, not the equivalent of XAML).

    Using the <Window.DataContext> syntax is the exact equivalent, i.e. it sets the DataContext property of the window. You can set the DataContext programmtically like this:

    this.DataContext = new Person();

    ...and in the XAML markup like this:

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

    It does the same thing, i.e. setting a property, and the results will be the same

    Please refer to the following page for a list of different MVVM instantiation approaches: http://paulstovell.com/blog/mvvm-instantiation-approaches

    >>Assuming it is true that we do not want to declare variables in XAML, we do not want to use Window.DataContext or any use of DataContext like that in XAML.

    No, <Window.DataContext> is property element syntax for setting a property. It doesn't define a variable.

    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Saturday, July 2, 2016 12:00 PM
  • just trying to help.

    Saturday, July 2, 2016 12:20 PM
  • I've got it, at least almost. If I do the following for the Window but not in the constructor:

    public Person person { get; set; } = new Person();

    Then I don't need to set the DataContext if I use the following for the XAML.

    For the Window:

    DataContext="{Binding RelativeSource={RelativeSource Self}}"

    For the binding:

    Text="{Binding Path=person.Name}"

    The problem is that any changes to the data after the InitializeComponent are not applied. I assume there is a fix for that. Note that in a realistic situation, this would be a problem. It is not for the "Person" object in the article's sample code since it automatically initializes itself.



    Sam Hobbs
    SimpleSamples.Info

    Tuesday, July 5, 2016 10:34 AM
  • >>I've got it, at least almost. If I do the following for the Window but not in the constructor:

    This simply sets the DataContext of the window to itself instead of setting it to the Person object. You then bind to properties of the window class (e.g. Person) instead of binding directly to properties of the Person class. It doesn't make much sense not to set the DataContext to the Person object directly if you intend to bind to properties of the Person class.

    >>The problem is that any changes to the data after the InitializeComponent are not applied. I assume there is a fix for that.

    The Person class should implement the INotifyPropertyChanged interface and raise the PropertyChanged event whenever a data bound property is updated dynamically: https://msdn.microsoft.com/en-us/library/ms743695(v=vs.100).aspx

    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Tuesday, July 5, 2016 10:44 AM
  • This simply sets the DataContext of the window to itself instead of setting it to the Person object. You then bind to properties of the window class (e.g. Person) instead of binding directly to properties of the Person class.

    The important thing is that I was a bit hasty and that code is not a direct equivalent. I have something more appropriate that I will put in a separate post.

    The Person class should implement the INotifyPropertyChanged interface and raise the PropertyChanged event whenever a data bound property is updated dynamically: https://msdn.microsoft.com/en-us/library/ms743695(v=vs.100).aspx

    Perhaps I should have stated explicitly that this is for educational purposes only. The article's sample code is not intended to be realistic and correspondingly this question is not expected to have a realistic answer.



    Sam Hobbs
    SimpleSamples.Info

    Tuesday, July 5, 2016 10:21 PM
  • The following markup creates an instance of the Person class and set the window's DataContext property to this instance:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApplication1"
            mc:Ignorable="d"
            Title="Window2" Height="300" Width="300">
        <Window.DataContext>
            <local:Person />
        </Window.DataContext>
    ...

    This is the XAML equivalent of creating an instance of an object and set the DataContext property programmatically:

    Person person = new Person();
    this.DataContext = person;
    Note that you said "creates an instance".


    Sam Hobbs
    SimpleSamples.Info

    Sunday, July 24, 2016 8:27 AM
  • ...and in the XAML markup like this:

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

    It does the same thing, i.e. setting a property, and the results will be the same

    No, in the MSDN sample, an instance of the item is created in C#. Your code is not the equivalent.


    Sam Hobbs
    SimpleSamples.Info

    Sunday, July 24, 2016 8:30 AM
  • There is no other way...

    You are an expert; I am not calling you a beginner, but a beginner can say "There is no other way". I was hoping an expert would provide a convincing explanation of that being the case.


    Sam Hobbs
    SimpleSamples.Info

    Sunday, July 24, 2016 8:38 AM
  • The equivalent of the following C#:

    this.DataContext = person;

    Would be the following XAML in the Window tag:

    DataContext="{Binding Source=person}"

    However the DataContext attribute is not recognized in that manner. In that context, XAML recognizes "person" as being a string literal, not a variable (or whatever term you want to use instead of "variable"). Therefore there is no direct equivalent in XAML of the sample C# code.



    Sam Hobbs
    SimpleSamples.Info

    Sunday, July 24, 2016 8:51 AM