使用datagrid并利用触发的事件在数据库上重复输入 [英] Duplicate entry on the database while using datagrid and utilizing triggered event
问题描述
我可以以某种方式禁用Datagrids在绑定数据库(在这种情况下为Entity Framework)中调用添加和保存方法的功能?我正在获得重复,我认为它是由datagrid本身发起的。
Can I somehow disable the Datagrids ability to invoke Add and Save methods on the binded database, in this case Entity Framework? I'm getting duplicate and I assume its initiated by the datagrid itself.
我使用datagrid通过其$ code添加新元素DataGridRowEditEndingEventArgs 触发器。通过使用Mvvm Lights通用
RelayCommand
在 viewModel
我触发了这种方法:
I'm using datagrid to add new element via its DataGridRowEditEndingEventArgs
trigger. By using Mvvm Lights generic RelayCommand
on viewModel
I'm triggering this method:
private void DataGridRowEditEndingExecute(DataGridRowEditEndingEventArgs e)
{
var device = new Device();
var newDevice = e.Row.DataContext as Device;
if (_isInsertMode)
{
if (newDevice != null)
{
var insertRecord = MessageBox.Show("Do you want to add " + newDevice.Name + " as a new device?", "Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (insertRecord == MessageBoxResult.Yes)
{
device.DeviceId = 0;
device.Name = newDevice.Name;
device.Supplier = newDevice.Supplier;
device.Category = newDevice.Category;
device.Description = newDevice.Description;
device.TimeCreated = DateTime.Now;
_context.Devices.AddDevice(device);
_context.Devices.Load();
_context.Complete();
RaisePropertyChanged(() => DeviceCollection);
MessageBox.Show(device.Name + " has being added!", "Inserting Record", MessageBoxButton.OK,
MessageBoxImage.Information);
}
else
{
_context.Devices.Load();
RaisePropertyChanged(() => DeviceCollection);
}
_context.Complete();
}
}
}
_context.Complete();
总是将两套实体保存到数据库中。一个具有正确的时间戳,一个没有它。之后,最后一个 _context.Complete()
调用删除没有时间戳的那个
The _context.Complete();
always saves two sets of the entity into database. One with the correct timestamp and one without it. After this the following last _context.Complete()
call removes the one without the timestamp?
这是datagrid xaml :
Here's the datagrid 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.DeviceCollection}"
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>
<i:Interaction.Triggers>
<i:EventTrigger EventName="RowEditEnding">
<command:EventToCommand PassEventArgsToCommand="True" Command="{Binding DeviceDatabaseViewModel.DataGridRowEditEndingCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="PreviewKeyDown">
<command:EventToCommand PassEventArgsToCommand="True" Command="{Binding DeviceDatabaseViewModel.DataGridPreviewKeyDownCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="AddingNewItem">
<command:EventToCommand PassEventArgsToCommand="True" Command="{Binding DeviceDatabaseViewModel.DataGridAddingNewItemCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="BeginningEdit">
<command:EventToCommand PassEventArgsToCommand="True" Command="{Binding DeviceDatabaseViewModel.DataGridBeginningEditCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
,并将datagrid绑定到此ICollectionView中(可能不是最正确的方法?)
and the datagrid is binded into this ICollectionView (maybe not the most correct approach?)
public ICollectionView DeviceCollection
{
get
{
_context.Devices.Load();
_deviceCollection = CollectionViewSource.GetDefaultView(_context.Devices.GetLocal());
return _deviceCollection;
}
set
{
if (_deviceCollection == null)
{
return;
}
_deviceCollection = value;
RaisePropertyChanged("DeviceCollection");
}
}
推荐答案
原因是你触发 DataGridRowEditEndingExecute
函数,然后在这里添加项。在你的 ObservableCollection
(说它的名字 o
)有这个事件: o.CollectionChanged + = o_CollectionChanged;
。你应该使用它,而不是手动添加项目。
The reason is you trigger DataGridRowEditEndingExecute
function then add item here. In your ObservableCollection
(say it name o
) have this event: o.CollectionChanged += o_CollectionChanged;
. You should use this instead, don't add item manually.
using System.Collections.Specialized;
bool isAddedbyApp = false;
void o_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add) // User add new item
{
foreach(var item in e.NewItems)
{
if (!isAddedbyApp)
{
var entity = item as Device; // or your Model
// Do some thing here: ask user, ..., validate value
// If you don't want this item, you call call remove function to remove it
}
}
}
}
您还有检查您的应用程序或用户在处理之前是否添加了项目。
You also have check if items is added by your app or user before process it.
当您的应用程序(而不是由用户)添加项目时,设置 isAddedbyApp = true;
。完成后,设置 isAddedbyApp = false;
When an item is added by your app (not by user) set isAddedbyApp = true;
. When finished, set isAddedbyApp = false;
这篇关于使用datagrid并利用触发的事件在数据库上重复输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!