2011-08-10 243 views
8

我想在WPF中DataGrid綁定到我的視圖模型,以便它將更新任何細胞對數據庫的更改,以及允許用戶刪除行並添加新行。我有一部分工作,但無法找到ADD和修改的ELEGANT解決方案。 這裏是XAMLWPF數據網格與MVVM

<DataGrid AutoGenerateColumns="false" HorizontalAlignment="Left" Margin="26,41,0,0" Name="dataGrid1" 
       ItemsSource="{Binding Path=GetAllItems}" Height="200" VerticalAlignment="Top" Width="266" > 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding Path=ItemListID}" Header="ID" Visibility="Hidden"/> 
      <DataGridTextColumn Binding="{Binding Path=ItemName}" Header="Name" Width="4*" /> 
      <DataGridCheckBoxColumn Binding="{Binding Path=IsActive}" Header="Active" Width="*" /> 
     </DataGrid.Columns> 

然後在我的視圖模型方法

private ObservableCollection< ItemsList> getAllItems() 
{ 
    using (var context = new InspectorGeneralEntities()) 
    { 
     var query = from I in context.ItemsLists 
        select I; 

     var item = new ObservableCollection<ItemsList>(query.ToList()); 
     return item; 
    } 
} 

刪除一行或在數據網格修改行不流到數據庫。

一)我需要什麼其他具有約束力的XAML代碼,將檢測這些事件

二)如何檢測已刪除的記錄或修改項目視圖模型,以便我可以更新的DataContext創建如果它不會自動。

回答

1

只需訂閱您的ObservableCollection的CollectionChanged事件。事件處理程序接收NotifyCollectionChangedEventArgs類的實例,該實例包含一個屬性「Action」,用於描述是否添加或刪除了行。它還包含已添加('NewItems')或已刪除('OldItems')的行的列表。這應該給你足夠的信息來更新你的數據庫。

您可以在您的行ViewModel中執行INotifyPropertyChanged(我猜想是ItemsList),然後訂閱它,以確定某行是否髒並需要在數據庫中更新。該接口由一個事件PropertyChanged組成,只要值發生更改,該事件將在ViewModel的屬性設置器中引發。

你說得對的NotifyCollectionChanged事件來要求立即插入到數據庫爲時尚早。但是,您可以將該行標記爲「插入」到事件處理程序中,並在完成行所需的最後一個屬性更改事件(請參閱上文)後立即插入該行。

+1

兩個問題; 1)NotifyCollectionChangedAction只會在添加新行或刪除時存在,如果您修改現有行中的單元格,則不會觸發。即無法判斷行是否髒。 2)當你第一次開始輸入NEW行時,NotifyCollectionChangedAction.Add在你有機會填充所有單元格之前被觸發。您不能將一個空行添加到數據庫,特別是如果此時仍有空字段。所以再次,你必須使用更新..再次,我不知道如何捕獲。 – Josef

1

我在你的問題中看到了一些代碼問題。但是,爲什麼刪除行不會反映在數據庫中的原因是.ToList() - 基本上你創建一個新的列表,它是查詢的副本,網格刪除從該副本的元素。

您應該使用的ListCollectionView和使用過濾而不是LINQ語句。

這裏是展示如何做到這一點的例子:

1)創建一個新的WPF項目,稱爲ListCollectionViewTest

2)在MainWindow.xaml.cs切&粘貼以下(應該是在視圖模型,但我懶得)

using System.Collections.Generic; 
    using System.Linq; 
    using System.Windows; 
    using System.Windows.Data; 

    namespace ListCollectionViewTest 
    { 
     /// <summary> 
     /// Interaction logic for MainWindow.xaml 
     /// </summary> 
     public partial class MainWindow : Window 
     { 
      private List<Employee> equivalentOfDatabase = new List<Employee>() 
         { 
          new Employee() { FirstName = "John", LastName = "Doe", IsWorthyOfAttention = true }, 
          new Employee() { FirstName = "Jane", LastName = "Doe", IsWorthyOfAttention = true }, 
          new Employee() { FirstName = "Mr.", LastName = "Unsignificant", IsWorthyOfAttention = false }, 
         }; 

      public ListCollectionView TestList { get; set; } 
      public MainWindow() 
      { 
       DataContext = this; 

       // This is all the magic you need ------- 
       TestList = new ListCollectionView(equivalentOfDatabase); 
       TestList.Filter = x => (x as Employee).IsWorthyOfAttention; 

       InitializeComponent(); 
      } 

      private void Button_Click(object sender, RoutedEventArgs e) 
      { 
       MessageBox.Show(equivalentOfDatabase.Aggregate("Employees are: \n\r", (acc, emp) => acc + string.Format(" - {0} {1}\n\r", emp.FirstName, emp.LastName), x => x)); 
      } 
     } 

     public class Employee 
     { 
      public string FirstName { get; set; } 
      public string LastName { get; set; } 
      public bool IsWorthyOfAttention { get; set; } 
     } 
    } 

3)在MainWindow.xaml切&粘貼此:

<Window x:Class="ListCollectionViewTest.MainWindow" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      Title="MainWindow" Height="350" Width="525"> 

     <StackPanel> 
      <DataGrid ItemsSource="{Binding TestList}" 
         RowHeight="22" 
         AutoGenerateColumns="True"> 
      </DataGrid> 
      <Button Content="Show All Employees in DB" Click="Button_Click" /> 
     </StackPanel>   
    </Window> 
0

你的數據上下文沒有你將作出udpates的時間存在。您正在使用破壞上下文的「使用」語句。您看到數據的唯一原因是您已經強制查詢針對您的數據庫運行(通過.ToList()語句)。回答你的問題:

a)沒有更多需要特別綁定 b)調用您的InspectorGeneralEntities()上下文中的SaveChanges()將更新您的數據庫中的任何更改。

0

您可以創建一個新的ViewModel CLass:ItemGridVM來表示每個行對象,即ItemGridVM公開您正在綁定到您的數據網格中的Item類屬性。 如:

public class ItemGridVM : BaseViewModel 
    { 
    private Item _item;//an instance of Item class 
     public int ItemId 
       { 
        get 
        { 
         return _item.ItemId; 
        } 
        set 
        { 
         _item.ItemId = value; 
         //if you want UI changes : raise PropertyChanged Notification and binding in UI should be Update SourceTrigger:PropertyChanged 
        } 
     } 
    //Contains Commands :UpdateItem,EditItem,DeleteItem 
} 

現在yourMainViewModel您可以創建ItemGridVM的可觀察集合爲:

private ObservableCollection<ItemGridVM> _getAllItems; 

public ObservableCollection<ItemGridVM> GetAllItems 
{ 
get 
      { 
       return _getAllItems; 
      } 
      set 
      { 
       _getAllItems = value; 
       //if u want Observable Collection to get updated on edit either 
       RaisePropertyChanged("GetAllItems"); 

      } 
} 

現在在任何行的任何行動的情況下,命令結合ItemGridVM.So u得到的行細節作爲暴露的屬性。 (純MVVM)