Here is my simple model.
public class Product
{
public String Name { get; set; }
public int Price { get; set; }
public String Info { get; set; }
}
When I use this in viewmodel as following:
public MainViewModel()
{
Item = new Product() { Name = "Coffee", Price = 4, Info = "Coffe is hot" };
}
protected Product _item;
public Product Item
{
get { return _item; }
set
{
_item = value;
NotifyPropertyChanged("Item");
}
}
In my XAML, I am binding to the nested properties.
<StackPanel>
<TextBox Text="{Binding Item.Name}"/>
<TextBox Text="{Binding Item.Price}"/>
<TextBox Text="{Binding Item.Info}"/>
<Button Content="Change Item" Click="Change_Item_Clicked"/>
</StackPanel>
I change only nested property in the click event:
private void Change_Item_Clicked(object sender, RoutedEventArgs e)
{
MainViewModel vm = DataContext as MainViewModel;
vm.Item.Name = "Donut";
}
This obviously doesn't update the UI since the parent property implements INotifyPropertyChanged
but not the nested one.
So I came up with the following solution and it does then update the UI fine.
I am essentially creating viewmodel version of the Product
class as below that implments INotifyPropertyChanged
.
public class ProductVM : Notifier
{
protected Product _p;
public ProductVM(Product p)
{
_p = p;
}
public String Name
{
get { return _p.Name; }
set
{
_p.Name = value;
NotifyPropertyChanged("Name");
}
}
public int Price
{
get { return _p.Price; }
set
{
_p.Price = value;
NotifyPropertyChanged("Price");
}
}
public String Info
{
get { return _p.Info; }
set
{
_p.Info = value;
NotifyPropertyChanged("Info");
}
}
}
Now the viewmodel use its version of the Product class as defined above that has ability to notify on changes.
class MainViewModel : Notifier
{
public MainViewModel()
{
Item = new ProductVM( new Product() { Name = "Coffee", Price = 4, Info = "Coffe is hot" });
}
protected ProductVM _item;
public ProductVM Item
{
get { return _item; }
set
{
_item = value;
NotifyPropertyChanged("Item");
}
}
}
This works great but what do you guys think of this approach? If we are going to bind to a property (nested or top level), wouldn't it be best for all these properties to implment the INotifyPropertyChanged?
What naming conversion can I use to name ProductVM
better? Is there a less cody way to achieve this?
List<Product>
but now viewmodel will have 'List<ProductVM>' I wonder if this be frown upon in anyway? \$\endgroup\$