2013-02-19 46 views
1

我想在我的WPF項目上使用實體框架獲取/操作數據來實現MVVM模式。 我很困惑,我想知道在哪裏驗證我的模型對象集合到數據庫的變化應該是? 我的應用程序如下:在我看來,我有一個人的數據網格,兩個文本框,將加載所選人員的姓名,一個按鈕更新行更改和一個按鈕刪除選定的行。使用實體框架實現MVVM模式 - 添加刪除

在我的ModelView中,我有一個observableCollection,它將在我的數據庫(實體)+兩個用於添加/刪除按鈕的繼電器命令(請查看下面的代碼)的類初始化時加載。

的問題是,我不明白MVVM,何時何地以及如何對我的數據的修改應推到數據庫的良好的理念是什麼? 現在,當我更新我的數據庫中的一行,並且將我的數據庫上下文修改保存在我的observable集合上時,但是當我刪除一個項目時它不是cdase,我必須在數據庫中手動查找它並將其刪除(我已經將我的observablecollection附加到一個NotifyCollectionChangedEventHandler事件來處理這個事件)...我沒有明白使用Observable集合的意義!

是否有使用數據庫中的數據「完美」的MVVM架構的任何簡單的解釋??? 謝謝! 我的ViewModel

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Collections.ObjectModel; 
using System.Windows.Data; 
using System.ComponentModel; 
using System.Windows.Input; 
using System.Windows; 
using MVVMOK.Models; 
using MVVMOK.Base; 
using System.Collections.Specialized; 

namespace MVVMOK.ViewModel 
{ 
    class MainWindowViewModel : ViewModelBase 
    { 
     private DW_MargoEntities contexte; 



     //Constructor 
     public MainWindowViewModel() 
     { 
      contexte = new DATABASEEntities(); 
      collectionOfCollaborators = new ObservableCollection<Collaborator>(); 
      foreach (Collaborator c in contexte.Collaborator) 
      { 
       collectionOfCollaborators.Add(c); 
      } 


      //Abonnement pour l'ajout ou la suppression d'éléments : 
      collectionOfCollaborators.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(collectionOfCollaboratorsChanged); 

      //Assignation des commandes : 
      this._deleteComand = new RelayCommand(new Action<object>(DeleteRow)); 
      this._updateCommand = new RelayCommand(new Action<object>(UpdateDB)); 
     } 
     //liste des propriétés publiques: 


     //Propriété pour représenter l'élément séléctionné du datagrid 
     private Collaborator selectedItem; 
     public Collaborator _selectedItem 
     { 
      get { return selectedItem; } 
      set 
      { 
       if (value != selectedItem) 
       { 
        selectedItem = value; 
        OnPropertyChanged("_selectedItem"); 
       }; 
      } 
     } 
     //Propriété pour représenter l'élément séléctionné: 
     private ObservableCollection<Collaborator> collectionOfCollaborators; 
     public ObservableCollection<Collaborator> _collectionOfCollaborators 
     { 
      get { return collectionOfCollaborators; } 
      set 
      { 
       this.collectionOfCollaborators = value; 
       OnPropertyChanged("_collectionOfCollaborators"); 
      } 
     } 

     //Commandes : 
     public ICommand _updateCommand 
     { 
      get; 
      set; 
     } 
     public ICommand _deleteComand 
     { 
      get; 
      set; 
     } 

     void collectionOfCollaboratorsChanged(object sender, NotifyCollectionChangedEventArgs e) 
     { 
      Collaborator f = new Collaborator(); 
      switch (e.Action) 
      { 
       case NotifyCollectionChangedAction.Add: 

        for(int i = 0; i<e.NewItems.Count;i++) 
        { 

         if (e.NewItems[i].GetType().Equals(f.GetType())) 
         { 
          contexte.Collaborator.Add(e.NewItems[i] as Collaborator); 
         } 
        } 
        contexte.SaveChanges(); 
        break; 

       case NotifyCollectionChangedAction.Remove: 

        for (int i = 0; i < e.OldItems.Count; i++) 
        { 

         if (e.OldItems[i].GetType().Equals(f.GetType())) 
         { 
          contexte.Collaborator.Remove(e.OldItems[i] as Collaborator); 
         } 
        } 
        contexte.SaveChanges(); 
        break; 
       //Reset = Clear 

      } 
     } 



     //Services : 
     public void UpdateDB(object msg) 
     { 
      contexte.SaveChanges(); 
     } 


     public void DeleteRow(object msg) 
     { 

      _collectionOfCollaborators.Remove(_selectedItem); 
      contexte.SaveChanges(); 
     } 
    } 
} 

我的模型

namespace MVVMOK.Models 
{ 
    using System; 
    using System.Collections.Generic; 

    public partial class Collaborator 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public string Surname { get; set; } 
    } 
} 

我的XAML

<Window x:Class="MVVMOK.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:MVVMOK.ViewModel" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <!-- Declaratively create an instance of our SongViewModel --> 
     <local:MainWindowViewModel /> 
    </Window.DataContext> 
    <Grid> 
     <Grid Height="237" HorizontalAlignment="Left" Margin="12,12,0,0" Name="grid1" VerticalAlignment="Top" Width="479"> 
      <DataGrid AutoGenerateColumns="False" Height="237" HorizontalAlignment="Left" Name="dataGrid1" VerticalAlignment="Top" Width="479" ItemsSource="{Binding Path=_collectionOfCollaborators, Mode=TwoWay}" SelectionMode="Single" SelectedItem="{Binding Path=_selectedItem, Mode=TwoWay}" > 
       <DataGrid.Columns> 
        <DataGridTextColumn Binding="{Binding Path=Id}" Header="ID" /> 
        <DataGridTextColumn Binding="{Binding Path=Name}" Header="Name" Width="4*" /> 
       </DataGrid.Columns> 
      </DataGrid> 
     </Grid> 
     <TextBox Height="23" HorizontalAlignment="Left" Margin="104,255,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text ="{Binding Path=_selectedItem.Name, Mode=TwoWay}" /> 
     <TextBox Height="23" HorizontalAlignment="Left" Margin="104,283,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" Text ="{Binding Path=_selectedItem.Surname, Mode=TwoWay}" /> 
     <Label Content="Name" Height="28" HorizontalAlignment="Left" Margin="50,255,0,0" Name="label1" VerticalAlignment="Top" /> 
     <Label Content="Surname" Height="28" HorizontalAlignment="Left" Margin="37,283,0,0" Name="label2" VerticalAlignment="Top" /> 
     <Button Content="Delete Row" Height="23" HorizontalAlignment="Left" Margin="416,260,0,0" Name="button1" VerticalAlignment="Top" Width="75" Command="{Binding Path=_deleteComand}"/> 
     <Button Content="Update All" Height="23" HorizontalAlignment="Left" Margin="335,260,0,0" Name="button2" VerticalAlignment="Top" Width="75" Command="{Binding Path=_updateCommand}"/> 
    </Grid> 
</Window> 

回答

0

我覺得這是不是 「」 方式MVVM總有幾個和像往常一樣,它依賴。

但到解決方案中有一個名爲IDataErrorInfo它可以幫助你的接口。

對於一個例子來看看這篇文章...... http://www.codeproject.com/Articles/98681/Validating-User-Input-WPF-MVVM

或者在這裏: http://blindmeis.wordpress.com/2012/04/16/wpf-mvvm-idataerrorinfo-validation-errortemplate/

也許你應該考慮從您的視圖模型隱藏實體框架與存儲庫模式或只需DataService

希望幫助...

1

我沒有回答,爲什麼你沒有看到您預期的結果,但我想我會給你如何構建這個好一點的一些想法。

當數據更改應用命令時,您真正想要做什麼。例如,應該應用刪除命令。處理這個命令時,你可以執行任何驗證,並保持更改或標記錯誤。因此,您在Relay命令中包裝的DeleteRow類應該是應用程序模型層中的單獨類。 您可以有一個使用MVVM的Web層,但它應該是持久性無知的,它應該應用一個命令,然後在命令成功或失敗時做出適當的反應。

this._deleteComand = new RelayCommand(new Action<object>(DeleteRow)); 

可能是更多的東西一樣

this._deleteComand = new RelayCommand(new Action<object>() => {new DeleteCommandHandler().Apply(new DeleteCommand(){SelectedItem = _selectedItem})}); 

的DeleteCommandHandler和DeleteCommand會形成模型的一部分(我會用不同的類庫這一點)。

現在您的處理程序需要了解您的持久性機制,因此您的處理程序中可以創建DW_MargoEntities上下文並執行刪除工作。

這樣做的好處是您的視圖模型不再負責更新您的模型,因此您的視圖模型將會簡單得多,並且不會直接依賴於您使用的數據庫。

一旦你有一個命令處理程序模式設置,我會轉向你的上下文的依賴注入。例如,如果不是說說新的DeleteCommandHandler(),你可以要求一個反轉控制容器,比如結構圖來構建它。

ObjectFactory.GetInstance<DeleteCommandHandler>(); 

然後你DeleteCommandHandler類可能看起來像

class DeleteCommandHandler 
{ 
    DW_MargoEntities context; 
    public DeleteCommandHandler(DW_MargoEntities context) 
    { 
     this.context = context; 
    } 

    public bool Apply(DeleteCOmmand command) 
    { 
     if (not valid) {return false;} 
     var item = context.LoadEntityById<EntityTypeHere>(command.SelectedItem) // Query the item 

     context.Delete(item); 
     return true; 
    } 
} 

對不起,我是一個有點模糊,這是一個很多解釋和它的晚在這裏變得有點。閱讀命令模式http://en.wikipedia.org/wiki/Command_pattern

+2

實際上,爲什麼我沒有看到結果是因爲ObservableCollection僅在更新元素(如我在某些論壇和討論中看到的)時才通知,而不是在添加或刪除實體時通知... The MSDN文檔真的很模糊! – Mohtaa 2013-02-19 12:20:51