Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting DataContext of elements inside XAML?

Tags:

wpf

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!

like image 993
Foysal94 Avatar asked Aug 12 '14 14:08

Foysal94


2 Answers

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>
like image 153
Abbas Avatar answered Nov 08 '22 12:11

Abbas


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.

like image 21
Kcvin Avatar answered Nov 08 '22 11:11

Kcvin