我有一个 DataGrid ,我在 RowEditEnding 上设置了一个事件处理程序来执行数据更新并使用 DataGridRowEditEndingEventArgs.Cancel 来保持如果更新因任何原因失败,则用户在同一行上。在同步上下文中,这很好。但是,我正在重构async / await模式的数据更新,并希望保留相同的用户交互 - 也就是说,用户无法在一行中保留未保存的更改 - 更改必须成功更新或用户必须明确取消编辑。我还希望尽量减少到数据存储的往返 - 只对 RowEditEnding 或同等事件进行更新。
问题在于使用async / await模式,尝试更新的结果仅在 RowEditEnding 方法返回后确定,因此我无法使用 DataGridRowEditEndingEventArgs.Cancel < / strong>了。我似乎需要确保选中编辑的行并处于编辑模式,但调用 BeginEdit(),即无参数重载不会重新激活编辑模式( RowEditEnding 如果我跳出行,则不会被触发)。
如何强制数据网格回到 RowEditEnding 事件范围之外的编辑状态?
同步方式(工作正常):
public class MyData
{
// Properties, etc...
public void Save()
{
// Synchronously saves to database, throws exception on error
}
}
void MyGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
if (e.EditAction == DataGridEditAction.Commit)
{
var item = (MyData)e.Row.Item;
try
{
item.Save();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
e.Cancel = true;
}
}
}
async / await方式......根据需要不起作用:
public class MyData
{
// Properties, etc...
public Task Save()
{
// Asynchronously saves to database, throws exception on error
}
}
async void MyGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
if (e.EditAction == DataGridEditAction.Commit)
{
var item = (MyData)e.Row.Item;
try
{
await item.Save();
}
catch (Exception ex)
{
// We get here on an exception thrown from Save
MessageBox.Show(ex.Message);
e.Cancel = true; // <== pointless, we're not in the execution scope of the event handler any more
MyGrid.SelectedItem = item; // We reselect the offending item
MyGrid.BeginEdit(); // Has no apparent effect
}
}
}
答案 0 :(得分:0)
找到一个解决方法,不确定它是否符合&#34;最佳&#34;做法:
public class MyData
{
// Properties, etc...
public Task Save()
{
// Asynchronously saves to database, throws exception on error
}
}
void MyGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
if (e.EditAction == DataGridEditAction.Commit)
{
var item = (MyData)e.Row.Item;
try
{
// Force the awaitable task to complete synchronously
// Have to use Task.Run to keep the awaited task from deadlocking
var task = Task.Run(async () => { await item.Save(); });
task.Wait();
}
catch (Exception ex)
{
// We get here on an exception thrown from Save
MessageBox.Show(ex.Message);
e.Cancel = true; // <== Can do this just as before
}
}
}