Mech0z
Mech0z

Reputation: 3647

Databinding not working with ViewModel

Cant get any data to work with databinding, I have the INotify event, I have the binding on the xaml objects, but nothing shows up, if I change the content on the lables to "something" it works, but nothing shows on load or on click on my button

My Xaml view

<Grid>
    <StackPanel Name="stackpanel">
        <Label Content="{Binding Name}" />
        <Label Content="{Binding Length}" />
        <Label Content="{Binding Rating}" />
        <Button Content="Change text" Click="ButtonClick" />
    </StackPanel>
</Grid>

Its codebehind

public partial class Movie
{
    readonly MovieViewModel _movieViewModel;

    public Movie()
    {
        InitializeComponent();
        _movieViewModel = new MovieViewModel { Movie = { Name = "The Dark Knight", Length = 180, Rating = 88 } };
        stackpanel.DataContext = _movieViewModel;
    }

    private void ButtonClick(object sender, RoutedEventArgs e)
    {
        _movieViewModel.Movie.Name = "bad movie";
    }
}

The View Model

class MovieViewModel
{
    public MovieViewModel() : this(new Movie())
    {
    }

    public MovieViewModel(Movie movie)
    {
        Movie = movie;
    }

    public Movie Movie { get; set; } 
}

The Model

class Movie : INotifyPropertyChanged
{
    public Movie()
    {}

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            NotifyPropertyChanged("Name");
        }
    }

    private int _length;
    public int Length
    {
        get { return _length; }
        set 
        { 
            _length = value;
            NotifyPropertyChanged("Length");
        }
    }

    private int _rating;
    public int Rating
    {
        get { return _rating; }

        set
        {
            if (_rating == value) return;
            _rating = value;
            NotifyPropertyChanged("_Rating");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Upvotes: 0

Views: 172

Answers (3)

Jarek
Jarek

Reputation: 3379

You have your bindings set incorrectly, that's the reason nothing is being shown.

Just take a closer look at your ViewModel and than on the bindings. You try to bind to property named Name but your MovieViewModel does not expose any property with that name. I'm pretty sure binding errors were reported to you (look through messages in Output window).

To make it work, you need either expose properties in your ViewModel to match the ones you try to bind to (bad), or change bindings in your xaml to have correct path:

<Label Content="{Binding Movie.Name}" />
<Label Content="{Binding Movie.Length}" />
<Label Content="{Binding Movie.Rating}" />

This should get you going.

Additionally - you may want to implement INotifyPropertyChanged also on your MovieViewModel class if you plan to change Movie object that is assigned to Movie property. As long as you will only change properties of Movie object already assigned to MovieViewModel everything will be ok, but if you would try to change actual object assigned to this property, no changes notifications will be generated and your UI will stop working correctly.

Moreover - I noticed that you made your NotifyPorpertyChanged method public - I wouldn't advise this as anyone can now trigger this event. Normal approach is to make such methods private or protected, depending if you want to provide way to trigger event from inheriting classes (which is very likely in case of PropertyChanged event).

Upvotes: 3

Pankaj Upadhyay
Pankaj Upadhyay

Reputation: 13574

Rather than using Label, I would suggest you to use Texblock. Try the following code

_movieViewModel = new MovieViewModel 
                      { Movie = { Name = "The Dark Knight", Length = 180, Rating = 88 } };
 this.DataContext = _movieViewModel;

and

Textblock like following

<StackPanel Name="stackpanel">
    <TextBlock Name="textBlock1" Text="{Binding Path=Name}"/>
    <TextBlock Name="textBlock2" Text="{Binding Path=Length}"/>
    <Button Content="Change text" Click="ButtonClick" />
</StackPanel>

Upvotes: 0

Haris Hasan
Haris Hasan

Reputation: 30097

I think you have one typing mistake

NotifyPropertyChanged("_Rating");

Should be

 NotifyPropertyChanged("Rating");

Upvotes: 1

Related Questions