0
votes

I have a EditUserViewModel which binds a User model. In the User model I have public properties such as Firstname, Lastname, Age, etc.

EditUserViewModel

public class EditUserViewModel : BindableBase
{
    private User _user;

    public EditUserViewModel(User user)
    {
        SaveCommand = new DelegateCommand(EditUser, CanSaveCommand);
        CancelCommand = new DelegateCommand(Cancel);
        User = user;
    }

    public User User
    {
        get{ return _user; }
        set
        {
            _user = value;
            OnPropertyChanged(() => User);
            SaveCommand.RaiseCanExecuteChanged();
        }
    }

    public DelegateCommand SaveCommand { get; set; }
    public ICommand CancelCommand { get; set; }

    public Func<bool> CanSaveCommand { get { return CanEditUser; } }

    private void EditUser()
    {
        Confirmed = true;
        FinishInteraction();
    }

    private bool CanEditUser()
    {
        if (string.IsNullOrEmpty(_user.Firstname) || _user.Firstname.Length < 3) return false;
        if (string.IsNullOrEmpty(_user.Lastname) || _user.Lastname.Length < 3) return false;

        return true;
    }
}

EditUserView

<UserControl x:Class="UserModule.Views.EditUserView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <TextBlock FontWeight="Bold" Grid.Row="0" Grid.Column="0">First name:</TextBlock>
        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=User.Firstname, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

        <TextBlock FontWeight="Bold" Grid.Row="1" Grid.Column="0">First name:</TextBlock>
        <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=User.Lastname, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

        <Button x:Name="OkButton" Grid.Row="2" Grid.Column="0" Command="{Binding SaveCommand}" Content="OK"/>
        <Button x:Name="CancelButton" Grid.Row="2" Grid.Column="1" Command="{Binding CancelCommand}" Content="Cancel"/>
    </Grid>

</UserControl>

User

public User 
{
    public string Firstname  { get; set; }
    public string Lastname  { get; set; }
    public string Age  { get; set; }
}

However, when I change the firstname or the lastname, the User property does not trigger its setter. But if I, instead of using a User class property, have Firstname and Lastname string properties in the Viewmodel, their setters gets triggered when I change their values in the GUI. Do I need to do anything specific to make this class property binding work?

3
Please paste your Model class also in the question. So that it would be easy to figure out the issueVimal CK
You don't change the User object via your view bindings, bur rather its properties Lastname and Firstname. That's correct behavior, there's no issue here.dymanoid
dymanoid: Alright. So the correct way would be to create properties for Firstname, Lastname, etc. in the viewmodel-class that binds to the User property?Tobias Johansson
Your model is not implemented Notification feature. Implement BindableBase for your model and tryVimal CK

3 Answers

2
votes

Make sure the User Class implements The INotifyPropertyChanged

  public class User : INotifyPropertyChanged
{
    private String _firstname;
    public String Firstname
    {
        get
        {
            return _firstname;
        }

        set
        {
            if (_firstname == value)
            {
                return;
            }

            _firstname = value;
            OnPropertyChanged();
        }
    } 
    private String _lastName;
    public String LastName
    {
        get
        {
            return _lastName;
        }

        set
        {
            if (_lastName == value)
            {
                return;
            }

            _lastName = value;
            OnPropertyChanged();
        }
    }
    public ObservableCollection<DataGridEntry> DataGridEntries { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
1
votes
    public class User : BindableBase
    {
       private string _firstName;
       private string _lastName;
       private string _age;

    public string Firstname  
    { 
      get{ return _firstName;} 
      set
      {
           _firstName = value;
           OnPropertyChanged(() => Firstname);
      }
    }

    public string LastName
    { 
      get{ return _lastName;} 
      set
      {
           _lastName = value;
           OnPropertyChanged(() => LastName);
      }
    }

    public string Age
    { 
      get{ return _age;} 
      set
      {
           _age = value;
           OnPropertyChanged(() => Age);
      }
    }
}
0
votes

Implementing INotifiyPropertyChanged in the class User itself should allow the binding to happen through the ViewModel.

http://msdn.microsoft.com/fr-fr/library/system.componentmodel.inotifypropertychanged%28v=vs.110%29.aspx