2

In my XAML I am doing the following

<Label Content="{Binding ElementName=Root, Path=UserData.Email, Mode=OneWay}" />

the Root element is my Window itself and the UserData Is a get; private set; auto property in my codebehind file, the Email property is get-only and is of type string.

the UserData object gets set after the user has logged in. But the binding is not taking the value from the object. I have verified that the object does indeed contain the correct data and isn't null. What am I missing here?

5
  • Are you setting the Datacontext of your label to your Model? Commented May 21, 2016 at 11:22
  • No, how should I do this? Since I haven't used DataContext before, guess ill read up a bit on what it is. Commented May 21, 2016 at 11:27
  • 1
    Well first you need a class that implements INotifyPropertyChanged This class would be your Model View part. Then you need to instantiate an object of that class and set the DataContext to the object. Basically so it knows where to look. You really need to find a good tutorial. Commented May 21, 2016 at 11:36
  • It seems that you also misunderstood the implementation of the MVVM-pattern. What you need is a view model that contains your prepared data for the view (window). Then you're able to bind a property of that view model to a control property on the view. For connecting both sides, you must set the window's DataContext either in its code behind, or directly in its XAML-code. Commented May 21, 2016 at 11:38
  • just get rid of the private set make it public Commented May 21, 2016 at 11:50

1 Answer 1

3

I went ahead and created a hello world version for this. Here is the xml. This should simply change the banner when the button is clicked to the text in the text box. I couldn't find a super simple example so I just made one. Obviously there are way more advanced ways to do this but it should make for a simple version to build from.

<Window x:Class="Hello_World.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">
    <Grid>
        <Label Name="MyLabel" Content="{Binding MyLabel}" HorizontalAlignment="Left" Margin="58,37,0,0" VerticalAlignment="Top" Height="65" Width="423" FontSize="44"/>
        <TextBox Name="MyTextBox" HorizontalAlignment="Left" Height="28" Margin="163,162,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="163"/>
        <Button Content="Change Banner" HorizontalAlignment="Left" Margin="251,209,0,0" VerticalAlignment="Top" Width="109" Click="Button_Click"/>

    </Grid>
</Window>

Next is the ModelView that implements the INotifyPropertyChanged interface. Note that your properties must be public properties with a getter, setter and backing field. This allows you to call the OnPropetyChanged() method whenever the property is set.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Hello_World
{
    public class MainViewModel: INotifyPropertyChanged
    {


        private string _myLabel;

        public string MyLabel
        {
            get { return _myLabel; }
            set
            {
                _myLabel = value;
                OnPropertyChanged(nameof(MyLabel));
            }
        }    

        public event PropertyChangedEventHandler PropertyChanged;

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

        }

    }
}

Lastly the MainWindow. Set the DataContext in the main constructor. Note I could have set the DataContext of the main grid and all of its children would inherit the same DataContext. This would keep you from having to set all of the components' individually.

namespace Hello_World
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private MainViewModel MyViewModel;


        public MainWindow()
        {
            InitializeComponent();
            MyViewModel = new MainViewModel();

            // Here's where I'm setting the object to look at.
            DataContext = MyViewModel;

            // Now I don't need to access the textbox directly.
            MyViewModel.MyLabel = "Hello World";    
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Note: ICommand is a more advanced topic.
            MyViewModel.MyLabel = MyTextBox.Text;
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the effort and explanation. If I can make a small suggestion, I would use nameof when calling the OnPropertyChanged from your MyLabel Property

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.