Qual é a melhor maneira de expor um objeto Model em um ViewModel?

5

Em um aplicativo WPF MVVM, expus meu objeto de modelo em meu viewModel criando uma instância da classe Model (que causa dependência) no ViewModel. Em vez de criar propriedades de VM separadas, eu envolvo as propriedades do modelo dentro da minha propriedade ViewModel.

Meu modelo é apenas uma classe de proxy gerada por uma estrutura de entidade:

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; }
}

Aqui está o meu 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
}

Aqui está minha classe de serviço:

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();
        }
    }


}

Eu expus meu objeto de modelo em meu viewModel criando uma instância dele usando uma nova palavra-chave. Também instanciei minha classe DataService na VM. Eu sei que isso causará uma strong dependência.

Então:

  1. Qual é a melhor maneira de expor um objeto Model em um ViewModel?
  2. Qual é a melhor maneira de usar o DataService na VM?
por Angel 05.06.2014 / 11:14
fonte

1 resposta

2

Como regra geral, não é uma boa idéia expor um objeto Model em um objeto ViewModel. A forma da classe ViewModel deve ser determinada pelas necessidades da View que a usará. A forma da classe Model deve ser determinada pelas preocupações do seu modelo de dados.

Na minha experiência com o Entity Framework e o padrão MVVM, descobri que é melhor transformar os dados do EF enquanto preencho meu objeto ViewModel. O objeto ViewModel conterá os dados do modelo de dados, mas de uma forma diferente. Se você precisa permitir que o usuário altere os dados, muitas vezes você quer ter métodos que transformem os dados ViewModel modificados de volta nos dados do Modelo para que você possa persistir no seu armazenamento de dados.

    
por 22.11.2016 / 20:01
fonte