Qual è il modo migliore per esporre un oggetto Model in un ViewModel?

5

In un'applicazione MVVM WPF, ho esposto il mio oggetto modello nel mio viewModel creando un'istanza di classe Model (che causa dipendenza) in ViewModel. Invece di creare proprietà VM separate, avvolgo le proprietà del modello all'interno della mia proprietà ViewModel.

Il mio modello è solo una classe proxy generata da un framework di entità:

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

Ecco il mio 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
}

Ecco la mia classe di servizio:

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


}

Ho esposto il mio oggetto modello nel mio viewModel creando un'istanza di esso usando una nuova parola chiave, inoltre ho istanziato la mia classe DataService in VM. So che questo causerà una strong dipendenza.

Quindi:

  1. Qual è il modo migliore per esporre un oggetto Model in un ViewModel?
  2. Qual è il modo migliore di utilizzare DataService in VM?
posta Angel 05.06.2014 - 11:14
fonte

1 risposta

2

Come regola generale, non è una buona idea esporre un oggetto Model in un oggetto ViewModel. La forma della classe ViewModel dovrebbe essere determinata dalle esigenze della vista che la utilizzerà. La forma della classe Model deve essere determinata dalle preoccupazioni del tuo modello di dati.

Nella mia esperienza con Entity Framework e il pattern MVVM, ho trovato la soluzione migliore per trasformare i dati EF mentre popolavo il mio oggetto ViewModel. L'oggetto ViewModel conterrà quindi i dati dal modello di dati ma in una forma diversa. Se è necessario consentire all'utente di modificare i dati, spesso si desidera disporre di metodi che trasformino i dati modificati di ViewModel in dati del modello, in modo da poterli conservare nell'archivio dati.

    
risposta data 22.11.2016 - 20:01
fonte

Leggi altre domande sui tag