6
votes

Hi am trying to get the hang of binding.

The XAML code:

<Window x:Class="WPF_SandBox.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">
    <StackPanel x:Name="stackPanel">
        <TextBox x:Name="textBox_FirstName" Width="200" Margin="0,100,0,0" Text="{Binding Path=FirstName, UpdateSourceTrigger=PropertyChanged}"  />
        <TextBox x:Name="textBox_LastName" Width="200" Margin="0,10,0,0" Text="{Binding Path=LastName, UpdateSourceTrigger=PropertyChanged}" />
        <TextBlock x:Name="textBlock_FullName"  Background="LightBlue" Width="200" Margin="0,10,0,0" Text="{Binding Path=FullName, UpdateSourceTrigger=PropertyChanged}"  />
    </StackPanel>
</Window>

The C# code:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Person person = new Person { FirstName = "Matt", LastName = "Smith" };
            stackPanel.DataContext = person;

        }
    }

    public class Person : INotifyPropertyChanged
    {
        string firstName;
        string lastName;

        public string FirstName
        {
            get
            { 
                return firstName;
            }
            set
            {
                firstName = value;
                OnPropertyChanged("FirstName");
                OnPropertyChanged("FullName");
            }
        }

        public string LastName
        {
            get { return lastName; }
            set
            {
                lastName = value;
                OnPropertyChanged("LastName");
                OnPropertyChanged("FullName");
            }
        }

        public string FullName
        {
            get
            {
                return String.Format("{0}, {1}",lastName,firstName);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
    }

When started, a window with 2 textboxes and 1 textblock shows. Inside the window constructor, I have created an instance of person and assigned the DataContext of the stackPanel to this instance. The first textbox is binded to the FirstName property of the Person class, the second TextBox is binded to the LastName property and the final TextBlock just prints the LastName property followed by the FirstName properties. As I said earlier, I set the DataContext of the stackPanel inside the C# code. How can I set it instead inside the XAML? For example:

<StackPanel x:Name="stackPanel" DataContext="person">
        <TextBox x:Name="textBox_FirstName" Width="200" Margin="0,100,0,0" Text="{Binding Path=FirstName, UpdateSourceTrigger=PropertyChanged}"  />
        <TextBox x:Name="textBox_LastName" Width="200" Margin="0,10,0,0" Text="{Binding Path=LastName, UpdateSourceTrigger=PropertyChanged}" />
        <TextBlock x:Name="textBlock_FullName"  Background="LightBlue" Width="200" Margin="0,10,0,0" Text="{Binding Path=FullName, UpdateSourceTrigger=PropertyChanged}"  />
    </StackPanel>

This doesn't work, but as you can see I am trying to set the DataContext of the stackPanel inside the XAML, how would I do it?

Thanks!

3
This deserves and upvote because you're making an attempt to learn WPF properly. When you figure out bindings, definitely start focusing on following MVVM design. Its relieving to see someone come on SO and not be completely brain dead! - Kcvin
@NETscape Well am currently learning how to make windows 8 store apps, and WPF is a big part of that. Other then MVVM, is there anything else I should focus on? - Foysal94
Reading MVVM resources will teach you what you need to know, you are also always welcome to the WPF chat. - Kcvin

3 Answers

5
votes

This brief article explains the two ways of setting the DataContext: through XAML or through code. Here's the code:

public class HelloWorldDataContextModel
{
    public string HelloWorld { get; set; }

    public HelloWorldDataContextModel()
    {
        HelloWorld = "Hello world!";   
    }
}

And the XAML:

<Window x:Class="HelloWorldDataContext.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
        xmlns:local="clr-namespace:HelloWorldDataContext"        
        Title="MainWindow" Height="350" Width="525">    

    <Window.Resources>
        <local:HelloWorldDataContextModel x:Key="HelloWorldDataContext" />   
    </Window.Resources>    

    <Grid DataContext="{StaticResource HelloWorldDataContext}">        
        <TextBox HorizontalAlignment="Left" Height="23" Margin="222,127,0,0" TextWrapping="Wrap" Text="{Binding HelloWorld}" VerticalAlignment="Top" Width="120"/>    
    </Grid>
</Window>
1
votes

To add to Abbas's answer, when you have a parameterless constructor, which you might find happen more often when applying MVVM, you can also set the DataContext of a control a difference way.

<Window x:Class="HelloWorldDataContext.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
        xmlns:local="clr-namespace:HelloWorldDataContext"        
        Title="MainWindow" Height="350" Width="525">    

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

    <Grid>        
        <TextBox HorizontalAlignment="Left" Height="23" Margin="222,127,0,0" TextWrapping="Wrap" Text="{Binding HelloWorld}" VerticalAlignment="Top" Width="120"/>    
    </Grid>
</Window>

You will get the same result using mine or Abbas's method; however when parameter's are required by a constructor, it's not worth it to go about this way.

0
votes

I dont know why you trying to set DataContext of StackPanel though you can set DataContext of Window and use it further, but still if you want to then try this

xaml

 <StackPanel x:Name="stackPanel" DataContext="{Binding Person}">

xaml.cs

    public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        Person = new Person { FirstName = "Matt", LastName = "Smith" };
    }
    Person person;
    public Person Person
    {
        get { return person; }
        set { person = value; OnPropertyChanged("Person"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

Or instead of Setting DataContext of StackPanel use dataContext of Window and Bind textblock text like Person.FirstName .....

<TextBox x:Name="textBox_FirstName" Width="200" Margin="0,100,0,0" Text="{Binding Path=Person.FirstName, UpdateSourceTrigger=PropertyChanged}"  />
    <TextBox x:Name="textBox_LastName" Width="200" Margin="0,10,0,0" Text="{Binding Path=Person.LastName, UpdateSourceTrigger=PropertyChanged}" />
    <TextBlock x:Name="textBlock_FullName"  Background="LightBlue" Width="200" Margin="0,10,0,0" Text="{Binding Path=Person.FullName, UpdateSourceTrigger=PropertyChanged}"  />