I am very new to this MVVM idea, was trying to write my first MVVM application to get my feet wet. Got a little bit of progress but hit road block as I progress. My question is a very basic fundamental one that could be easily addressed with code behind, but it was discouraged to do so as it violates the loose coupling principal I guess. So this is the problem I have:
My Model:
public class ToDoItemModel
{
private DateTime _TodoDate;
private string _TodoDescription;
private TimeSpan _TodoTimeSpan;
private string _StartTime;
public string StartTime
{
get { return _StartTime; }
set
{
_StartTime = value;
}
}
public TimeSpan ToDoTimeSpan
{
get { return _TodoTimeSpan; }
set
{
_TodoTimeSpan = value;
}
}
public string ToDoDescription
{
get { return _TodoDescription; }
set
{
_TodoDescription = value;
}
}
public DateTime ToDoDate
{
get { return _TodoDate; }
set
{
_TodoDate = value;
}
}
public override string ToString()
{
return string.Format("Date: {0}- Time: {1}- Duration: {2}- Description: {3}",_TodoDate.ToString("d"),_StartTime,_TodoTimeSpan,_TodoDescription);
}
}
My viewModel:
public class ToDoListModelView:INotifyPropertyChanged
{
List<ToDoItemModel> _myModel = new List<ToDoItemModel>();
public ICommand AddToDo
{
get
{
return new RelayCommand(addToDo);
}
}
public ToDoListModelView()
{
_myModel.Add(new ToDoItemModel() { ToDoDate = DateTime.Now, ToDoDescription = "Testing 1" });
_myModel.Add(new ToDoItemModel() { ToDoDate = DateTime.Now.AddDays(1), ToDoDescription = "Testing 2" });
}
public List<ToDoItemModel> myModel
{
get { return _myModel; }
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
var handler = this.PropertyChanged;
if (handler!=null)
{
handler(this, e);
}
}
public void RaisePropertyChanged(string PropertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(PropertyName));
}
private void addToDo()
{
_myModel.Add(new ToDoItemModel() { ToDoDate = DateTime.Now.AddDays(2), ToDoDescription = "From Relay Command" });
RaisePropertyChanged("DataGridChanged");
}
}
The viewModel implements INotifyPropertyChanged, and use a class RelayCommand that implements ICommand interface.
My view is:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestWPF" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="TestWPF.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="1,0,-1,0" d:DataContext="{d:DesignData /SampleData/ToDoListModelSampleData.xaml}">
<Button x:Name="AddToDoButton" Content="Add Todo Item
"
HorizontalAlignment="Left" Margin="419,90,0,0" VerticalAlignment="Top" Width="78" Height="33.04"
Command="{Binding AddToDo}"/>
<DataGrid x:Name="TodoList" HorizontalAlignment="Left"
Margin="33,184,0,0" VerticalAlignment="Top"
RenderTransformOrigin="-0.833,-0.846" Height="108" Width="464"
ItemsSource="{Binding myModel}"
Style="{DynamicResource ToDoEntry}"/>
</Grid>
</Window>
When I hit F5 the application ran and the 2 initial records were displayed.
However, when I hit the button add, I saw the new record was added internally but the datagrid was not updated. I know the datagrid needs to be refreshed somehow, but I am not sure how to tell the grid to refresh the way MVVM is supposed to handle. My current code behind is as simple as that:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ToDoListModelView();
}
}
According to the documentation I read from Microsoft site and if I understand it correctly, RaisePropertyChange is supposed to flag a change event occurs, I am just confused how to tie the event to refresh the grid using xaml without any code behind. Please help.
Change your List<ToDoItemModel>
to an ObservableCollection<ToDoItemModel>
A List<T>
does not notify the UI to update when an item gets added or removed from the collection, while an ObservableCollection<T>
does.