What's the best way to expose a Model object in a ViewModel?
- by Angel
In a WPF MVVM application, I exposed my model object into my viewModel by creating an instance of Model class (which cause dependency) into ViewModel. Instead of creating separate VM properties, I wrap the Model properties inside my ViewModel Property.
My model is just an entity framework generated proxy class:
public partial class TblProduct
{
public TblProduct()
{
this.TblPurchaseDetails = new HashSet<TblPurchaseDetail>();
this.TblPurchaseOrderDetails = new HashSet<TblPurchaseOrderDetail>();
this.TblSalesInvoiceDetails = new HashSet<TblSalesInvoiceDetail>();
this.TblSalesOrderDetails = new HashSet<TblSalesOrderDetail>();
}
public int ProductId { get; set; }
public string ProductCode { get; set; }
public string ProductName { get; set; }
public int CategoryId { get; set; }
public string Color { get; set; }
public Nullable<decimal> PurchaseRate { get; set; }
public Nullable<decimal> SalesRate { get; set; }
public string ImagePath { get; set; }
public bool IsActive { get; set; }
public virtual TblCompany TblCompany { get; set; }
public virtual TblProductCategory TblProductCategory { get; set; }
public virtual TblUser TblUser { get; set; }
public virtual ICollection<TblPurchaseDetail> TblPurchaseDetails { get; set; }
public virtual ICollection<TblPurchaseOrderDetail> TblPurchaseOrderDetails { get; set; }
public virtual ICollection<TblSalesInvoiceDetail> TblSalesInvoiceDetails { get; set; }
public virtual ICollection<TblSalesOrderDetail> TblSalesOrderDetails { get; set; }
}
Here is my ViewModel:
public class ProductViewModel : WorkspaceViewModel
{
#region Constructor
public ProductViewModel()
{
StartApp();
}
#endregion //Constructor
#region Properties
private IProductDataService _dataService;
public IProductDataService DataService
{
get
{
if (_dataService == null)
{
if (IsInDesignMode)
{
_dataService = new ProductDataServiceMock();
}
else
{
_dataService = new ProductDataService();
}
}
return _dataService;
}
}
//Get and set Model object
private TblProduct _product;
public TblProduct Product
{
get
{
return _product ?? (_product = new TblProduct());
}
set
{
_product = value;
}
}
#region Public Properties
public int ProductId
{
get
{
return Product.ProductId;
}
set
{
if (Product.ProductId == value)
{
return;
}
Product.ProductId = value;
RaisePropertyChanged("ProductId");
}
}
public string ProductName
{
get
{
return Product.ProductName;
}
set
{
if (Product.ProductName == value)
{
return;
}
Product.ProductName = value;
RaisePropertyChanged(() => ProductName);
}
}
private ObservableCollection<TblProduct> _productRecords;
public ObservableCollection<TblProduct> ProductRecords
{
get { return _productRecords; }
set
{
_productRecords = value;
RaisePropertyChanged("ProductRecords");
}
}
//Selected Product
private TblProduct _selectedProduct;
public TblProduct SelectedProduct
{
get
{
return _selectedProduct;
}
set
{
_selectedProduct = value;
if (_selectedProduct != null)
{
this.ProductId = _selectedProduct.ProductId;
this.ProductCode = _selectedProduct.ProductCode;
}
RaisePropertyChanged("SelectedProduct");
}
}
#endregion //Public Properties
#endregion // Properties
#region Commands
private ICommand _newCommand;
public ICommand NewCommand
{
get
{
if (_newCommand == null)
{
_newCommand = new RelayCommand(() => ResetAll());
}
return _newCommand;
}
}
private ICommand _saveCommand;
public ICommand SaveCommand
{
get
{
if (_saveCommand == null)
{
_saveCommand = new RelayCommand(() => Save());
}
return _saveCommand;
}
}
private ICommand _deleteCommand;
public ICommand DeleteCommand
{
get
{
if (_deleteCommand == null)
{
_deleteCommand = new RelayCommand(() => Delete());
}
return _deleteCommand;
}
}
#endregion //Commands
#region Methods
private void StartApp()
{
LoadProductCollection();
}
private void LoadProductCollection()
{
var q = DataService.GetAllProducts();
this.ProductRecords = new ObservableCollection<TblProduct>(q);
}
private void Save()
{
if (SelectedOperateMode == OperateModeEnum.OperateMode.New)
{
//Pass the Model object into Dataservice for save
DataService.SaveProduct(this.Product);
}
else if (SelectedOperateMode == OperateModeEnum.OperateMode.Edit)
{
//Pass the Model object into Dataservice for Update
DataService.UpdateProduct(this.Product);
}
ResetAll();
LoadProductCollection();
}
#endregion //Methods
}
Here is my Service class:
class ProductDataService:IProductDataService
{
/// <summary>
/// Context object of Entity Framework model
/// </summary>
private MaizeEntities Context { get; set; }
public ProductDataService()
{
Context = new MaizeEntities();
}
public IEnumerable<TblProduct> GetAllProducts()
{
using(var context=new R_MaizeEntities())
{
var q = from p in context.TblProducts
where p.IsDel == false
select p;
return new ObservableCollection<TblProduct>(q);
}
}
public void SaveProduct(TblProduct _product)
{
using(var context=new R_MaizeEntities())
{
_product.LastModUserId = GlobalObjects.LoggedUserID;
_product.LastModDttm = DateTime.Now;
_product.CompanyId = GlobalObjects.CompanyID;
context.TblProducts.Add(_product);
context.SaveChanges();
}
}
public void UpdateProduct(TblProduct _product)
{
using (var context = new R_MaizeEntities())
{
context.TblProducts.Attach(_product);
context.Entry(_product).State = EntityState.Modified;
_product.LastModUserId = GlobalObjects.LoggedUserID;
_product.LastModDttm = DateTime.Now;
_product.CompanyId = GlobalObjects.CompanyID;
context.SaveChanges();
}
}
public void DeleteProduct(int _productId)
{
using (var context = new R_MaizeEntities())
{
var product = (from c in context.TblProducts
where c.ProductId == _productId
select c).First();
product.LastModUserId = GlobalObjects.LoggedUserID;
product.LastModDttm = DateTime.Now;
product.IsDel = true;
context.SaveChanges();
}
}
}
I exposed my model object in my viewModel by creating an instance of it using new keyword, also I instantiated my DataService class in VM. I know this will cause a strong dependency.
So:
What's the best way to expose a Model object in a ViewModel?
What's the best way to use DataService in VM?