[英]WPF datagrid with MVVM
我正在嘗試將 WPF 中的數據網格綁定到我的 ViewModel,以便它將更新對數據庫的任何單元格更改,並允許用戶刪除行並添加新行。 我已經完成了部分工作,但找不到 ADD 和修改的優雅解決方案。 這是 xaml
<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>
然后在我看來 model 方法
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;
}
}
刪除行或修改數據網格上的行不會流入數據庫。
a) 我需要在 xaml 代碼中創建什么其他綁定來檢測這些事件
b) 我如何在 model 視圖中檢測到已刪除的記錄或修改的項目,以便如果它不會自動更新數據上下文。
我看到您問題中的代碼存在一些問題。 但是刪除行沒有反映在數據庫中的原因是.ToList() - 本質上,您正在創建一個新列表,它是查詢的副本,並且網格正在從該副本中刪除元素。
您應該使用ListCollectionView並使用Filter而不是 linq 語句。
這是一個示例,展示了如何執行此操作:
1) 創建一個名為ListCollectionViewTest的新 WPF 項目
2)在 MainWindow.xaml.cs 中剪切&粘貼以下內容(應該在 ViewModel 但我太懶了)
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>
只需訂閱 ObservableCollection 的 CollectionChanged 事件。 事件處理程序接收NotifyCollectionChangedEventArgs class 的實例,其中包含描述是否已添加或刪除行的屬性“操作”。 它還包含已添加('NewItems')或刪除('OldItems')的行列表。 這應該為您提供足夠的信息來更新您的數據庫。
您可以在行 ViewModel 中實現INotifyPropertyChanged (我猜是ItemsList
類),然后訂閱它,以查明行是否臟並需要在數據庫中更新。 該接口由單個事件PropertyChanged
組成,每當值更改時,它將在 ViewModel 的屬性設置器中引發。
沒錯,NotifyCollectionChanged 事件來得太早,無法立即插入數據庫。 但是您可以在事件處理程序中將該行標記為“已插入”,並在完成該行所需的最后一個屬性更改事件(見上文)發生時立即插入它。
在您進行更新時,您的數據上下文不存在。 您正在使用破壞上下文的“使用”語句。 您看到數據的唯一原因是您已強制對您的數據庫運行查詢(通過 .ToList() 語句)。 要回答您的問題:
a) 不需要專門用於綁定 b) 在 InspectorGeneralEntities() 上下文中調用 SaveChanges() 將更新數據庫中的任何更改。
您可以創建一個新的 ViewModel CLass:ItemGridVM 來表示每一行 object 即 ItemGridVM 公開您在數據網格中綁定的項目 class 屬性。 例如:
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 的 Observable COllection,如下所示:
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。因此,您可以將行詳細信息作為公開的屬性。 我用這個解決了同樣的問題。(純MVVM)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.