2010-09-06 229 views
11

我正在尋找一個示例代碼/文章,它將演示WPF DataGrid與MVVM模式的行動以添加,更新和刪除數據庫中的記錄。WPF DataGrid使用MVVM添加,更新和刪除

我有一個特定的要求,允許用戶使用DataGrid插入新記錄而不是新的子窗體。

如果任何人都可以推薦優質資源或爲該特定任務提供樣本,那對我來說會很有幫助。

回答

1

我不知道有關這個問題的任何好的文章,但我沒有看到問題;只要你綁定到一個ObservableCollection或ListCollectionView,它包含的對象的類有一個默認的構造函數(我不認爲還有其他的限制),DataGrid會很好地處理事情。您綁定的集合必須有某種添加新項目的方式,這就是爲什麼您需要綁定到ICollection或IEditableCollectionView--後者是首選,因爲它具有控制項目創建的特定選項 - 請參閱AddNew,CanAddNew等, DataGrid的工作良好。

+0

在我的情況下,問題是要確定哪一行更改/刪除 – Musaab 2011-09-03 14:51:44

+0

我不知道我跟着你。新項目與DataGrid一起工作的方式是,有一個NewItemPlaceholder(默認情況下,其結構與其他任何DataGrid行相同),聚焦時創建一個新的臨時數據項,並在提交時(失去焦點,輸入關鍵字等)插入該集合中的該項目。 IIRC一切都是硬編碼的,所以也許你不能隨心所欲改變,但你應該嘗試一下,這對我來說已經足夠了。 – 2011-09-06 10:20:20

+0

讓我們忘記新項目,讓我們談談現有的項目,我如何刪除一行,刪除意味着從網格和數據庫中刪除它,這裏是我的問題 – Musaab 2011-09-07 11:26:01

2

這裏CodeProject上是關於WPF的DataGrid + MVVM圖案的物品:

http://www.codeproject.com/KB/WPF/MVVM_DataGrid.aspx

+1

您鏈接到的項目不會添加或更新,只會使用刪除按鈕進行刪除,而不是使用DataGrid的刪除行進行刪除。我也發現,試圖找到關於如何使用MVVM用於使用DataGrid的CRUD操作的真實世界示例令人非常沮喪!我開始認爲MVVM是一個神話。 – SurfingSanta 2015-08-12 07:08:55

1

編輯:粘貼的部分,它適合你的問題。 整個文章:http://www.codeproject.com/Articles/30905/WPF-DataGrid-Practical-Examples

此示例演示如何使用DataGrid通過綁定執行CRUD操作,其中數據庫集成通過數據訪問層(DAL)解耦。

建築學

這個例子是一個簡單的CRUD應用程序,允許用戶編輯Northwind數據庫的Customers表項。該示例具有一個數據訪問層,該數據訪問層公開了對簡單數據對象進行操作的查找/刪除/更新方法,以及一個表示層,以便可以通過WPF框架有效地綁定這些對象。由於我們只執行CRUD功能,因此我沒有添加業務邏輯層(BLL);如果你是純粹主義者,你可以添加一個pass-through BLL;不過,我覺得這個例子會增加一點。

該架構內的關鍵類如下所示:

數據訪問層暴露用於管理客戶數據對象的生命週期的接口。實現此接口的類使用類型化的DataSet作爲數據庫集成層;然而,這對DAL的客戶是隱藏的。該層的存在意味着我們不直接連接到數據庫模式或產生的數據集架構,即我們可以改變我們的模式,但仍提供以下爲我們的客戶提供的接口:

public interface ICustomerDataAccessLayer 
{ 
    /// Return all the persistent customers 
    List<CustomerDataObject> GetCustomers(); 

    /// Updates or adds the given customer 
    void UpdateCustomer(CustomerDataObject customer); 

    /// Delete the given customer 
    void DeleteCustomer(CustomerDataObject customer); 
} 
public class CustomerDataObject 
{ 
    public string ID { get; set; } 

    public string CompanyName { get; set; } 

    public string ContactName { get; set; } 
} 

正如你可以看到,DAL公開的UI框架沒有特定的接口或類(例如ObservableCollection)。這裏的問題是如何將由ICustomerDataAccess.GetCustomers返回的客戶綁定到我們的DataGrid,並確保更改與數據庫同步。

我們可以將DataGrid直接綁定到我們的客戶集合List;但是,我們需要確保在適當的時間點調用DAL接口上的UpdateCustomer和DeleteCustomer方法。我們可能採取的一種方法是處理DataGrid公開的事件/命令,以確定它剛剛執行或打算對綁定的客戶收集執行的操作。但是,在這樣做時,我們將編寫特定於DataGrid的集成代碼。如果我們想要更改UI以呈現ListView和多個TextBoxes(詳細信息視圖),該怎麼辦?我們將不得不重新編寫這個邏輯。另外,沒有一個DataGrid事件完全符合我們想要的。有「結束」事件,但沒有「結束」事件;因此,事件處理程序可見的數據不處於其提交狀態。更好的方法是如果我們能夠調整我們的Customer對象集合,使其可以綁定到任何合適的WPF UI控件,並通過DAL與數據庫同步添加/編輯/刪除操作。 處理刪除操作

ObservableCollection類非常適合我們的數據綁定需求。它暴露了一個CollectionChanged事件,每當添加或從集合中刪除項目時都會觸發該事件。如果我們將客戶數據複製到ObservableCollection並將其綁定到DataGrid,我們可以處理CollectionChanged事件並在DAL上執行所需的操作。以下代碼片段顯示了CustomerObjectDataProvider(它在XAML中定義爲ObjectDataProvider)如何構造CustomerUIObjects的ObservableCollection。這些UI對象只是簡單地包裝它們的數據對象以便公開相同的屬性。

public CustomerObjectDataProvider() 
{ 
    dataAccessLayer = new CustomerDataAccessLayer(); 
} 

public CustomerUIObjects GetCustomers() 
{ 
    // populate our list of customers from the data access layer 
    CustomerUIObjects customers = new CustomerUIObjects(); 

    List<CustomerDataObject> customerDataObjects = dataAccessLayer.GetCustomers(); 
    foreach (CustomerDataObject customerDataObject in customerDataObjects) 
    { 
     // create a business object from each data object 
     customers.Add(new CustomerUIObject(customerDataObject)); 
    } 

    customers.CollectionChanged += new 
     NotifyCollectionChangedEventHandler(CustomersCollectionChanged); 

    return customers; 
} 

void CustomersCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
    if (e.Action == NotifyCollectionChangedAction.Remove) 
    { 
     foreach (object item in e.OldItems) 
     { 
      CustomerUIObject customerObject = item as CustomerUIObject; 

      // use the data access layer to delete the wrapped data object 
      dataAccessLayer.DeleteCustomer(customerObject.GetDataObject()); 
     } 
    } 
} 

當用戶刪除與DataGrid控件一排,CollectionChanged事件上綁定的集合解僱。在事件處理程序中,我們使用作爲參數傳遞的包裝數據對象調用DAL DeleteCustomer方法。

處理刪除操作相對簡單,但是如何更新或插入?您可能認爲可以使用相同的方法,但NotifyCollectionChangedEventArgs.Action屬性確實包含添加操作;但是,更新集合中的項目時不會觸發此事件。此外,當用戶向DataGrid添加一個新項目時,該對象最初會以非初始化狀態添加到綁定集合中,因此我們只會看到具有其默認屬性值的對象。我們真正需要做的是確定用戶何時完成編輯網格中的項目。 處理更新/插入

要確定用戶何時完成編輯綁定項目,我們需要深入研究一下綁定機制本身。 DataGrid能夠執行當前正在編輯的行的原子提交;如果綁定項目實現公開BeginEdit,EndEdit和CancelEdit方法的IEditableObject接口,則這成爲可能。通常,實現此接口的對象將在調用BeginEdit方法時返回到其狀態,作爲對正在調用的CancelEdit方法的響應。但是,在這種情況下,我們並不擔心能夠取消編輯;我們真正需要知道的是用戶完成了一行的編輯。 DataGrid在綁定項目上調用EndEdit時會觸發此事件。

爲了通知EndEdit中已被調用的綁定集合中的對象之一CustomerDataObjectProvider中,CustomerUIObject實現IEditableObject如下:

public delegate void ItemEndEditEventHandler(IEditableObject sender); 

public event ItemEndEditEventHandler ItemEndEdit; 

#region IEditableObject Members 

public void BeginEdit() {} 

public void CancelEdit() {} 

public void EndEdit() 
{ 
    if (ItemEndEdit != null) 
    { 
     ItemEndEdit(this); 
    } 
} 

#endregion 

當項目被添加到CustomerUIObjects集合,這個事件集合中的所有項目的處理,與處理程序僅將事件轉發:

public class CustomerUIObjects : ObservableCollection<CustomerDataObject> 
{ 
    protected override void InsertItem(int index, CustomerUIObject item) 
    { 
     base.InsertItem(index, item); 

     // handle any EndEdit events relating to this item 
     item.ItemEndEdit += new ItemEndEditEventHandler(ItemEndEditHandler); 
    } 

    void ItemEndEditHandler(IEditableObject sender) 
    { 
     // simply forward any EndEdit events 
     if (ItemEndEdit != null) 
     { 
      ItemEndEdit(sender); 
     } 
    } 

    public event ItemEndEditEventHandler ItemEndEdit; 
} 

的CustomerObjectDataProvider現在可以處理此事件接收的通知在任何綁定項目上調用CommitEdit。然後它可以調用DAL方法來同步數據庫狀態:

public CustomerUIObjects GetCustomers() 
{ 
    // populate our list of customers from the data access layer 
    CustomerUIObjects customers = new CustomerUIObjects(); 

    List<CustomerDataObject> customerDataObjects = dataAccessLayer.GetCustomers(); 
    foreach (CustomerDataObject customerDataObject in customerDataObjects) 
    { 
     // create a business object from each data object 
     customers.Add(new CustomerUIObject(customerDataObject)); 
    } 

    customers.ItemEndEdit += new ItemEndEditEventHandler(CustomersItemEndEdit); 
    customers.CollectionChanged += new 
     NotifyCollectionChangedEventHandler(CustomersCollectionChanged); 

    return customers; 
} 

void CustomersItemEndEdit(IEditableObject sender) 
{ 
    CustomerUIObject customerObject = sender as CustomerUIObject; 

    // use the data access layer to update the wrapped data object 
    dataAccessLayer.UpdateCustomer(customerObject.GetDataObject()); 
} 

上述代碼將處理插入和更新操作。

總之,此方法將DAL提供的數據項和集合調整爲更適合WPF框架內數據綁定的UI項和集合。所有數據庫同步邏輯都是通過處理來自該綁定集合的事件來執行因此,沒有WPF DataGrid特定的代碼。

+1

雖然此鏈接可能會回答問題,但最好在此包含答案的重要部分,並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 – IngoAlbers 2015-10-20 07:48:20