My sample project (VS2012) is about working with ICommand(s) and contains two textboxes, a button, and a ListView, a Person class (model), a PersonViewModel class, a RelayCommand Class, and a Person.xaml view. On launching the project, I binded the
ListView to an ObservableCollection property in the ViewModel, and I populate this ObservableCollection in the ViewModel constructor with 2 Name/Address items (of type Person). The objective is that when I click a row in the ListView, the Name item will
appear in one textbox and the Address item in the next textbox. If I edit the textboxes, I want to click the Update button to update the changed items in the ListView.
Right now the textboxes are bound to the ListView, so when I click a row on the ListView the respective values automatically appear in the textboxes, and the ListView is bound to a Name property and Address property in the Person class (which contains
OnPropertyChanged events). So when I edit a textbox and click on the other textbox, the Listview Updates automatically. So the Update button is not even required in the scenario.
I have an Update Command in the ViewModel which I binded the Update button to, but it does not appear to be firing. I placed some break points in the code for the Update Command, but code execution never stops in the Update command after I click the
Update button. However, the RelayCommand appears to be getting invoked (I write "testing" to console in the RelayCommand Execute event) when I click the Update button
How do I get the Update command to fire (in the code below) ? If I comment out the OnPropertyChanged event in the Person (Model) class -- then the ListView does not automatically update after I edit the textboxes. But the Update button does not
fire. What code changes do I need to make so that the edits get updated in the ListView only after I click the Update button? How do I get the Update button to fire? This is purely an exercise for me to gain understanding of MVVM workings.
Person.xaml
<Window x:Class="myICommandSample.View.Person"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:myICommandSample.ViewModel"
Title="Person" Height="300" Width="300"><Window.DataContext><vm:PersonViewModel/></Window.DataContext><Grid><Grid.RowDefinitions><RowDefinition Height="auto"/><RowDefinition Height="auto"/><RowDefinition Height="*"/></Grid.RowDefinitions><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="100"></ColumnDefinition><ColumnDefinition Width="*"></ColumnDefinition></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="auto"></RowDefinition><RowDefinition Height="auto"></RowDefinition></Grid.RowDefinitions><Label x:Name="lblName" Content="Name" Grid.Row="0" Grid.Column="0" VerticalAlignment="Top"></Label><TextBox x:Name="txtName" Grid.Row="0" Grid.Column="1" VerticalAlignment="Top" Text="{Binding ElementName=lstPerson, Path=SelectedItem.Name}"></TextBox><Label x:Name="lblAddress" Content="Address" Grid.Row="1" Grid.Column="0" VerticalAlignment="Top"></Label><TextBox x:Name="txtAddress" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" Text="{Binding ElementName=lstPerson, Path=SelectedItem.Address}"></TextBox></Grid><Button x:Name="btnUpdate" Width="100" Height="20" HorizontalAlignment="Center" Grid.Row="1" Content="Update"
Command="{Binding UpdateCommand}" CommandParameter="{Binding ElementName=lstPerson, Path=SelectedItem.Address}"></Button><ListView x:Name="lstPerson" Grid.Row="2" ItemsSource="{Binding Persons}"><ListView.View><GridView><GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" /><GridViewColumn Header="Address" Width="200" DisplayMemberBinding="{Binding Address}"/></GridView></ListView.View></ListView></Grid></Window>
Person.cs (Model)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
namespace myICommandSample.Model
{
public class Person : INotifyPropertyChanged
{
private string name;
private string address;
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
OnPropertyChanged("Name");
}
}
public string Address
{
get
{
return address;
}
set
{
address = value;
OnPropertyChanged("Address");
}
}
}
}
PersonViewModel.cs (PersonViewModel class and RelayCommand class)
using System;
using System.Collections.Generic;
using System.Collections;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using myICommandSample.Model;
namespace myICommandSample.ViewModel
{
public class PersonViewModel
{
private ObservableCollection<Person> _personList;
public PersonViewModel()
{
_personList = new ObservableCollection<Person>()
{
new Person(){Name="Steve", Address="NY"},
new Person(){Name="John",Address="CA"}
};
}
public ObservableCollection<Person> Persons
{
get { return _personList; }
set { _personList = value; }
}
private ICommand mUpdater;
public ICommand UpdateCommand
{
get
{ //--nothing gets fired in here
if (mUpdater == null)
mUpdater = new RelayCommand();
return mUpdater;
}
set
{
mUpdater = value;
}
}
}
//------------------------------------------------------
class RelayCommand : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
Console.WriteLine("testing");
}
}
}
Rich P