ObservableCollection 事件上的 ItemEndEdit 触发两次的问题
我在数据网格插入/更新行两次时遇到问题。数据网格绑定到一个可观察集合,该集合添加了一个 ItemEndEdit 事件:
/// <summary>
/// extends the ObservableCollection class to include adding an ItemEndEdit event
/// </summary>
public class ObservableProjectExpenseItems : ObservableCollection<ProjectExpenseItemsBO>
{
protected override void InsertItem(int index, ProjectExpenseItemsBO item)
{
base.InsertItem(index, item);
item.ItemEndEdit += new ProjectExpenseItemsBO.ItemEndEditEventHandler((x) =>
{
if (ItemEndEdit != null)
ItemEndEdit(x);
});
}
public event ProjectExpenseItemsBO.ItemEndEditEventHandler ItemEndEdit;
}
ProjectExpenseItemsBO 是我的模型/业务对象,其中包含绑定在 dg 列中的属性。
当用户离开数据网格的行时,我在视图模型中使用以下内容来插入/更新记录:
void ProjectExpenseItemsItemEndEdit(IEditableObject sender)
{
ProjectExpenseItemsBO projectExpenseItemsBO = sender as ProjectExpenseItemsBO;
if (projectExpenseItemsBO.RowID == 0)
{
// if the ProjectExpenseItemsBO is a new row
projectExpenseItemsRepository.AddProjectExpenseItem(projectExpenseItemsBO, this.ProjectExpenseID);
}
else
{
projectExpenseItemsRepository.UpdateProjectExpenseItem(projectExpenseItemsBO);
}
// get the total of the project expense items
ItemTotal = projectExpenseItemsRepository.GetItemTotal(this.ProjectExpenseID);
}
更新和插入都会触发两次,我不明白为什么。我在类/视图模型的初始化中附加了 ItemEndEdit:
ObservableProjectExpenseItems projectExpenseItemsCollection;
List<ProjectExpenseItemsBO> list = new List<ProjectExpenseItemsBO>(projectExpenseItemsRepository.GetProjectExpenseItems(this.ProjectExpenseID));
list.ForEach(item => ProjectExpenseItemsCollection.Add(item));
ProjectExpenseItemsCollection.ItemEndEdit += new ProjectExpenseItemsBO.ItemEndEditEventHandler(ProjectExpenseItemsItemEndEdit);
最后,这是我的数据网格:
<DataGrid ItemsSource="{Binding Path=ProjectExpenseItemsCollection}" Grid.Row="0" Grid.Column="0" AutoGenerateColumns="False"
Name="dgProjectExpenseItems" SelectionMode="Single" SelectionUnit="FullRow" CanUserResizeColumns="True"
SelectedItem="{Binding Path=SelectedProjectExpenseItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
GridLinesVisibility="Horizontal" CanUserDeleteRows="True" CanUserAddRows="True">
<DataGrid.RowValidationRules>
<vr:RowDataInfoValidationRule ValidationStep="UpdatedValue" />
</DataGrid.RowValidationRules>
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Width="SizeToCells" IsReadOnly="True" MinWidth="50" Binding="{Binding RowID}" />
<DataGridTextColumn Header="Project Expense ID" IsReadOnly="True" Width="SizeToCells" Visibility="Hidden" MinWidth="0" Binding="{Binding ProjectExpenseID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Item Number" Width="SizeToCells" MinWidth="140" Binding="{Binding ItemNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Item Description" Width="SizeToCells" MinWidth="250" Binding="{Binding ItemDescription, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<!--<DataGridTextColumn Header="Qty" Width="SizeToCells" MinWidth="65" Binding="{Binding ItemQty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />-->
<DataGridTextColumn Header="Qty">
<DataGridTextColumn.Binding>
<Binding Path="ItemQty" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<vr:PositiveDecimalValidationRule ValidationStep="RawProposedValue" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Unit Price">
<DataGridTextColumn.Binding>
<Binding Path="ItemUnitPrice" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<vr:PositiveDecimalValidationRule ValidationStep="RawProposedValue" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<!--<DataGridTextColumn Header="Unit Price" Width="SizeToCells" MinWidth="90" Binding="{Binding ItemUnitPrice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />-->
<DataGridTextColumn Header="Supplier Name" Width="SizeToCells" MinWidth="200" Binding="{Binding SupplierName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataGrid.Columns>
</DataGrid>
I have an issue with a datagrid inserting/updating rows twice. The datagrid is bound to an observable collection that has an ItemEndEdit event added to it:
/// <summary>
/// extends the ObservableCollection class to include adding an ItemEndEdit event
/// </summary>
public class ObservableProjectExpenseItems : ObservableCollection<ProjectExpenseItemsBO>
{
protected override void InsertItem(int index, ProjectExpenseItemsBO item)
{
base.InsertItem(index, item);
item.ItemEndEdit += new ProjectExpenseItemsBO.ItemEndEditEventHandler((x) =>
{
if (ItemEndEdit != null)
ItemEndEdit(x);
});
}
public event ProjectExpenseItemsBO.ItemEndEditEventHandler ItemEndEdit;
}
ProjectExpenseItemsBO is my model/business object that contains the properties bound in the columns of the dg.
I use the following in my viewmodel to insert/update records when the user leaves the row of the datagrid:
void ProjectExpenseItemsItemEndEdit(IEditableObject sender)
{
ProjectExpenseItemsBO projectExpenseItemsBO = sender as ProjectExpenseItemsBO;
if (projectExpenseItemsBO.RowID == 0)
{
// if the ProjectExpenseItemsBO is a new row
projectExpenseItemsRepository.AddProjectExpenseItem(projectExpenseItemsBO, this.ProjectExpenseID);
}
else
{
projectExpenseItemsRepository.UpdateProjectExpenseItem(projectExpenseItemsBO);
}
// get the total of the project expense items
ItemTotal = projectExpenseItemsRepository.GetItemTotal(this.ProjectExpenseID);
}
Both the update and insert fire twice and I cannot figure out why. I attach the ItemEndEdit in the initialization of the class/viewmodel:
ObservableProjectExpenseItems projectExpenseItemsCollection;
List<ProjectExpenseItemsBO> list = new List<ProjectExpenseItemsBO>(projectExpenseItemsRepository.GetProjectExpenseItems(this.ProjectExpenseID));
list.ForEach(item => ProjectExpenseItemsCollection.Add(item));
ProjectExpenseItemsCollection.ItemEndEdit += new ProjectExpenseItemsBO.ItemEndEditEventHandler(ProjectExpenseItemsItemEndEdit);
Finally, here is my datagrid:
<DataGrid ItemsSource="{Binding Path=ProjectExpenseItemsCollection}" Grid.Row="0" Grid.Column="0" AutoGenerateColumns="False"
Name="dgProjectExpenseItems" SelectionMode="Single" SelectionUnit="FullRow" CanUserResizeColumns="True"
SelectedItem="{Binding Path=SelectedProjectExpenseItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
GridLinesVisibility="Horizontal" CanUserDeleteRows="True" CanUserAddRows="True">
<DataGrid.RowValidationRules>
<vr:RowDataInfoValidationRule ValidationStep="UpdatedValue" />
</DataGrid.RowValidationRules>
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Width="SizeToCells" IsReadOnly="True" MinWidth="50" Binding="{Binding RowID}" />
<DataGridTextColumn Header="Project Expense ID" IsReadOnly="True" Width="SizeToCells" Visibility="Hidden" MinWidth="0" Binding="{Binding ProjectExpenseID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Item Number" Width="SizeToCells" MinWidth="140" Binding="{Binding ItemNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Item Description" Width="SizeToCells" MinWidth="250" Binding="{Binding ItemDescription, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<!--<DataGridTextColumn Header="Qty" Width="SizeToCells" MinWidth="65" Binding="{Binding ItemQty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />-->
<DataGridTextColumn Header="Qty">
<DataGridTextColumn.Binding>
<Binding Path="ItemQty" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<vr:PositiveDecimalValidationRule ValidationStep="RawProposedValue" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<DataGridTextColumn Header="Unit Price">
<DataGridTextColumn.Binding>
<Binding Path="ItemUnitPrice" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<vr:PositiveDecimalValidationRule ValidationStep="RawProposedValue" />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
<!--<DataGridTextColumn Header="Unit Price" Width="SizeToCells" MinWidth="90" Binding="{Binding ItemUnitPrice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />-->
<DataGridTextColumn Header="Supplier Name" Width="SizeToCells" MinWidth="200" Binding="{Binding SupplierName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataGrid.Columns>
</DataGrid>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧。在尝试找出我遇到的另一个问题后,我偶然发现了导致事件触发两次的原因。当我在数据网格中保存一行时,我注意到保存前后主键字段值为零。显然,这是由于我在调用视图模型中的 save 方法后没有刷新集合。当我更改视图模型中的代码以刷新集合时:
重复记录的问题消失了。哇,我已经为此工作了几个星期了。有趣的是,如此基本的东西会让你陷入困境这么长时间,尤其是当你试图学习新东西(wpf、mvvm)时。
Alright. After trying to figure out a different issue I was having, I stumbled upon what was causing the event to fire twice. when I would save a row in the datagrid, I noticed the primary key field value was zero before and after the save. Obviously, this was due to me not refreshing the collection after the save method in my viewmodel was called. when I changed my code in the viewmodel to refresh the collection:
the problem with duplicate records went away. Wow, I have been working on this for a couple weeks now. funny how something so basic can throw you for a loop for so long, especially when you are trying to learn something new (wpf, mvvm).