我最初向Entity Framework here提出了与dataGrid插入/删除/保存操作相关的问题但是我无法完全获得建议的工作方法。到目前为止,这是我的方法:
ViewModel构造函数
public DeviceDatabaseViewModel()
{
LoadData();
}
LoadData
private void LoadData()
{
_context.Devices.Load();
_devices = _context.Devices.GetLocal();
_devices.CollectionChanged += Device_CollectionChanged;
DeviceCollectionView = (CollectionView)new CollectionViewSource { Source = _devices }.View;
}
事件
private bool _isAddedbyApp = false;
private void Device_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
var device = new Device();
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var item in e.NewItems)
{
var entity = item as Device;
if (entity == null) continue;
if (_isAddedbyApp) continue;
_isAddedbyApp = true;
_context.Devices.Add(entity);
_isAddedbyApp = false;
}
break;
case NotifyCollectionChangedAction.Remove:
foreach (var item in e.OldItems)
{
var entity = item as Device;
if (entity == null) continue;
if (_isAddedbyApp) continue;
_isAddedbyApp = true;
_context.Devices.Remove(entity);
_isAddedbyApp = false;
}
break;
//Reset = Clear
case NotifyCollectionChangedAction.Reset:
break;
}
}
XAML
<DataGrid
x:Name="DeviceListDataGrid"
Margin="0,25,0,0"
Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="6"
AutoGenerateColumns="False"
EnableRowVirtualization="True"
AlternatingRowBackground="LightBlue"
AlternationCount="2"
RowDetailsVisibilityMode="VisibleWhenSelected"
ItemsSource="{Binding DeviceDatabaseViewModel.DeviceCollectionView}"
SelectedItem="{Binding DeviceDatabaseViewModel.SelectedDevice}">
<DataGrid.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="DarkCyan"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="DarkCyan"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="DeviceIdentification" Header="Id" Width="200*" Binding="{Binding DeviceId, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn x:Name="DeviceName" Header="Name" Width="200*" Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn x:Name="DeviceDescriptionColumn" Header="Description" Width="200*" Binding="{Binding Description, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn x:Name="DeviceSupplier" Header="Supplier" Width="150*" Binding="{Binding Supplier, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn x:Name="DeviceCategory" Header="Category" Width="150*" Binding="{Binding Category, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
</DataGrid>
GetLocal
从实体框架数据库返回ObservableCollection
,该数据库也正在实施INotifyPropertyChanged
。
但是我无法为实体框架的SaveChanges
方法找到正确的位置,而且结构似乎有点偏离?
修改
如果我在活动结束时SaveChanges
放置了CollectionChanged
我的程序会挂起。实际上我有一些调试原因在SaveChanges()
方法中有一个MessageBox,在禁用之后,事情似乎或多或少都朝着正确的方向发展..
编辑2 添加设备实体定义。 Link to the file,因为它相当长......
MessageBox是通过此例外:
生成的{“ItemsControl与其项目源不一致。\ n请参阅 内部异常以获取更多信息。“}
{“开发人员的信息(使用Text Visualizer阅读 这个):\ r \ n这个异常被抛出,因为生成器用于控制 'System.Windows.Controls.DataGrid Items.Count:28'的名称 'DeviceListDataGrid'已收到CollectionChanged事件序列 不同意Items集合的当前状态。该 检测到以下差异:\ r \ n累计计数27为 与实际计数28不同。[累计计数为(最后计数) 重置+ #Adds - 自上次复位后#Removes。)\ r \ n在索引26处: Generator的项目“{NewItemPlaceholder}”与实际项目不同 'FxEditorDatabaseStructure.Core.Domain.Device'。\ r \ n \ r \ n一个或多个 以下来源可能引发了错误的事件:\ r \ n
System.Windows.Controls.ItemContainerGenerator \ r \ n
System.Windows.Controls.ItemCollection \ r \ n
System.Windows.Data.ListCollectionView \ r \ n
System.Collections.ObjectModel.ObservableCollection`1 [FxEditorDatabaseStructure.Core.Domain.Device, FxEditorDatabaseStructure,Version = 1.0.0.0,Culture = neutral, PublicKeyToken = null]] \ r \ n(已加星标的来源被认为更多 可能是导致问题的原因。)\ r \ n \ r \ n最常见的原因 是(a)更改集合或其计数而不提高 相应的事件,以及(b)提出索引不正确的事件 或项目参数。\ r \ n \ r \ n例外的堆栈跟踪描述了如何 检测到不一致,而不是它们是如何发生的。得到一个 更及时的例外,设置附加属性 生成器上的'PresentationTraceSources.TraceLevel'值为'High' 并重新运行该方案。一种方法是运行命令 类似如下:\ n
System.Diagnostics.PresentationTraceSources.SetTraceLevel(myItemsControl.ItemContainerGenerator, System.Diagnostics.PresentationTraceLevel.High)\ r \ n来自Immediate 窗口。这导致检测逻辑在每次运行之后运行 CollectionChanged事件,因此会降低应用程序的速度。\ r \ n“}开发人员的信息(使用Text Visualizer来阅读):这个 异常被抛出,因为生成器用于控制 'System.Windows.Controls.DataGrid Items.Count:28'的名称 'DeviceListDataGrid'已收到CollectionChanged事件序列 不同意Items集合的当前状态。该 检测到以下差异:累计计数27为 与实际计数28不同。[累计计数为(最后计数) 重置+ #Adds - 自上次重置后#Removes。)在索引26处: Generator的项目“{NewItemPlaceholder}”与实际项目不同 'FxEditorDatabaseStructure.Core.Domain.Device'。
答案 0 :(得分:1)
有几件事:
首先,您可以直接绑定到_devices
或您的热门ObservableCollection
变量,无需创建DeviceCollectionView
。
ItemsSource="{Binding DeviceDatabaseViewModel._devices}"
请务必进行_devices
公开访问。
其次,Device_CollectionChanged
函数存在问题,如果您应用上述更改,则可以这样做:
private bool _isAddedbyApp = false;
private void Device_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var item in e.NewItems)
{
MessageBox.Show(item.GetType().ToString()); // if not = "Device" then tell me because there something you bind don't correct
var entity = item as Device;
if (entity != null && !_isAddedbyApp)
{
if (MessageBox.Show("Add?", "", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
// add entity to database
// No need to call _devices.Add() here, you collection
// will auto be updated.
}
else
{
// remove this item
_devices.Remove(entity);
}
}
}
break;
}
}
第三,您仍然不知道如何使用_isAddedbyApp
变量。
仅在您的应用(非用户)添加设备时使用它。
_isAddedbyApp = true; // You start add items.
_context.Add(...);
_isAddedbyApp = false; // You finished add items.