1

I have my Model class which implements INotifyPropertyChanged. My View has 5 TextBox, 2 Button and a ListView to display grid. In my ViewModel I was previously adding default values to the ObservableCollection of my Model class and displaying it to a ListView.

The button implementation is done using ICommand and RelayCommand.

Now I want to add data to the ObservableCollection from the user from the UI TextBox. How can I achieve that? The UI TextBox hasbindings with properties of the Model class.

My View

<ListView Name="UserGrid" Grid.Row="1" Margin="4,178,12,13"  ItemsSource="{Binding UserDatas}"  >
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,7,0,0" Name="txtUserId" VerticalAlignment="Top" Width="178" Text="{Binding UserId}" />
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,35,0,0" Name="txtFirstName" VerticalAlignment="Top" Width="178" Text="{Binding FirstName}" />

Like these there are 5 TextBoxes

The Model class:

public class User : INotifyPropertyChanged
{
    private int userId;
    private string firstName;


public int UserId
    {
        get
        {
            return userId;
        }
        set
        {
            userId = value;
            RaisePropertyChanged("UserId");
        }
    }
}

The ViewModel:

public class UsersViewModel:INotifyPropertyChanged
{
    private ObservableCollection<User> userDatas;

    public ObservableCollection<User> UserDatas
    {
        get
        {
            if (userDatas == null)
            {
                userDatas = new ObservableCollection<User>();
            }
            return userDatas;
        }
        set
        {
            userDatas = value;
            RaisePropertyChanged("UserDatas");
        }
    }

}

   private CommandBase _LoadCommand;
   public ICommand LoadCommand
    {
        get
        {
            if (this._LoadCommand == null)
                this._LoadCommand = new CommandBase(LoadData);
            return this._LoadCommand;
        }
    }

   private void LoadData(object obj)
   {
        //What need to be done here to access the textboxes of UI which are binded to User.cs class.

       User newUser = new User();
       UserDatas.Add(newUser);
   }

Now what I need to write in the LoadData method to take inputfrom textboxes from UI and store it in my ObservableCollection

5
  • Make use of Inotifypropertychanged. Now create a getter setter string for the textbox and bind it. Now once you have inputted value add it to your observable collection and it should reflect. Commented Feb 5, 2016 at 7:45
  • You shouldn't bind your model to the UI, as the UI should be agnostic of the model and only know about the viewmodel Commented Feb 5, 2016 at 8:04
  • What do you have so far? Can you show basically how you've bound your properties on your view/viewmodel? Commented Feb 5, 2016 at 8:11
  • My Model and ViewModel implements INotifyPropertyChanged and the in the MainWindow.xaml the ListView is bound to ObservableCollection of Model class. Commented Feb 5, 2016 at 8:48
  • I have added my bits and pieces of code please review.Thanks Commented Feb 5, 2016 at 8:54

1 Answer 1

1

There are several things you can do. Most obvious, is to have a "Add New" Command, which creates a new empty object and stores it in a CurrentUser or SelectedUser property.

This property is bound to the Template's (or Form's) context. You'd have 3 commands (Add New User, Save User, Cancel to cancel addition of a new user creation).

For example

public class UsersViewModel : INotifyPropertyChanged
{
    public UsersViewModel() 
    {
        UserDatas = new ObservableCollection<User>();

        AddNewUserCommand = new RelayCommand(AddNewUser, param => !this.IsNewUser);
        SaveUserCommand = new RelayCommand(SaveUser);
        CancelNewUserCommand = new RelayCommand(CancelNewUser, param => this.IsNewUser);
    }

    private ObservableCollection<User> userDatas;
    public ObservableCollection<User> UserDatas
    {
        get { return userDatas; }
        set
        {
            userDatas = value;
            RaisePropertyChanged("UserDatas");
        }
    }

    private User selectedUser;
    public User SelectedUser 
    {
        get { return selectedUser; }
        set
        {
            selectedUser = value;
            RaisePropertyChanged("SelectedUser");
            RaisePropertyChanged("IsNewUser");
        }
    }

    public bool IsNewUser 
    {
        get 
        {
            if(SelectedUser==null)
                return false;

            return SelectedUser.UserId == 0;
        }
    }

    public ICommand AddNewUserCommand { get; private set; }
    public ICommand CancelNewUserCommand { get; private set; }
    public ICommand SaveUserCommand { get; private set; }

    private void AddNewUser() 
    {
        SelectedUser = new User();
    }

    private void SaveUser() 
    {
        // Just in case of concurency
        var newUser = SelectedUser;
        if(newUser == null) 
        {
            return;
        }

        var isNewUser = newUser.UserId == 0;

        // Persist it to the database
        this.userRepository.Add(newUser);
        this.userRepository.SaveChanges();

        // If all worked well, add it to the observable collection
        if(isNewUser) 
        {
            // Only add if new, otherwise it should be already in the collection
            UserDatas.Add(newUser)
        }
    }
}

But again, it's very discouraged to work directly on the model and bind it to the View. You should also create a ViewModel for your User and put validation (implement the IDataErrorInfo interface on the UserViewModel) in there and handling of state, for example tracking if the UserViewModel is dirty (i.e. data was changed).

All these are presentation concerns and not business logic, so they belong to a ViewModel and not to the Model itself.

Sign up to request clarification or add additional context in comments.

Comments

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.