/// <summary> /// /// </summary> /// <param name="async">When true, runs the specified server method in a seperate thread.</param> /// <param name="postApplying"> /// If specified, this function is called after applying is complete. It is the /// function's responsibility to call FloatingDialog.EndApplyChanges() in order to complete the apply cycle. /// </param> protected static void Dialog_ApplyingChanges <TableType, RowType>(TableType sourceTable, FloatingDialog dialog, MethodInfo saveMethod, CancelRoutedEventArgs e, object[] additionalArgs, bool async, Action postApplying) where TableType : DataTable, new() where RowType : DataRow { RowType editVersion = dialog.Content as RowType; DataTable changes = editVersion.Table.GetChanges(); // No changes were made, skip the apply (but don't cancel) if (changes == null) { e.Skip = true; if (postApplying != null) { postApplying(); } else { dialog.EndApplyChanges(e); } return; } // Remember data state DataRowState state = changes.Rows[0].RowState; // Will store updated data TableType savedVersion = null; object[] actualArgs = additionalArgs != null? new object[additionalArgs.Length + 1] : new object[1]; actualArgs[0] = Oltp.Prepare <TableType>(changes); if (additionalArgs != null) { additionalArgs.CopyTo(actualArgs, 1); } // Save the changes to the DB Delegate[] delegates = new Delegate[] { (Action) delegate() { using (OltpProxy proxy = new OltpProxy()) { savedVersion = (TableType)saveMethod.Invoke(proxy.Service, actualArgs); } }, (Func <Exception, bool>) delegate(Exception ex) { // Failed, so cancel and display a message MessageBoxError("Error while updating.", ex); e.Cancel = true; return(false); }, (Action) delegate() { // Special case when adding a new row if (state == DataRowState.Added) { // Import the saved row sourceTable.ImportRow(savedVersion.Rows[0]); // Even though nothing needs to be updated, mark it as added so AppliedChanges handled treats it properly RowType newRow = sourceTable.Rows[sourceTable.Rows.Count - 1] as RowType; newRow.SetAdded(); // Set as new target content dialog.TargetContent = newRow; dialog.Content = Dialog_MakeEditVersion <TableType, RowType>(sourceTable, newRow); } // Activate the post applying action if (postApplying != null) { postApplying(); } else { dialog.EndApplyChanges(e); } } }; if (async) { App.CurrentPage.Window.AsyncOperation(delegates[0] as Action, delegates[1] as Func <Exception, bool>, delegates[2] as Action); } else { bool exception = false; try { (delegates[0] as Action).Invoke(); } catch (Exception ex) { (delegates[1] as Func <Exception, bool>).Invoke(ex); exception = true; } if (!exception) { (delegates[2] as Action).Invoke(); } if (postApplying != null) { postApplying(); } else { dialog.EndApplyChanges(e); } } }
/// <summary> /// /// </summary> /// <param name="async">When true, runs the specified server method in a seperate thread.</param> /// <param name="postApplying"> /// If specified, this function is called after applying is complete. It is the /// function's responsibility to call FloatingDialog.EndApplyChanges() in order to complete the apply cycle. /// </param> protected static void Dialog_ApplyingChanges <TableT, RowT> ( TableT sourceTable, FloatingDialog dialog, MethodInfo saveMethod, CancelRoutedEventArgs e, object[] additionalArgs, bool async, Action postApplying ) where TableT : DataTable, new() where RowT : DataRow { RowT controlRow = dialog.Content as RowT; DataTable changes = controlRow.Table.GetChanges(); // No changes were made, skip the apply (but don't cancel) if (changes == null) { e.Skip = true; if (postApplying != null) { postApplying(); } else { dialog.EndApplyChanges(e); } return; } if (dialog.IsBatch) { // Copy all target rows and apply the changed values to them TableT clonedTargetTable = new TableT(); foreach (RowT row in (IEnumerable)dialog.TargetContent) { clonedTargetTable.ImportRow(row); } clonedTargetTable.AcceptChanges(); dialog.ApplyBindingsToItems(clonedTargetTable.Rows); // Get these changes changes = clonedTargetTable.GetChanges(); } // No changes were made, skip the apply (but don't cancel) if (changes == null) { e.Skip = true; if (postApplying != null) { postApplying(); } else { dialog.EndApplyChanges(e); } return; } // Remember data state DataRowState state = controlRow.RowState; // Will store updated data TableT savedVersion = null; // Create a typed version of the changes object[] actualArgs = additionalArgs != null? new object[additionalArgs.Length + 1] : new object[1]; actualArgs[0] = Oltp.Prepare <TableT>(changes); if (additionalArgs != null) { additionalArgs.CopyTo(actualArgs, 1); } // Save the changes to the DB Delegate[] delegates = new Delegate[] { (Action) delegate() { using (OltpProxy proxy = new OltpProxy()) { savedVersion = (TableT)saveMethod.Invoke(proxy.Service, actualArgs); } }, (Func <Exception, bool>) delegate(Exception ex) { // Failed, so cancel and display a message MainWindow.MessageBoxError("Error while updating.\n\nChanges may have been saved, if re-saving doesn't work please refresh the page.", ex); e.Cancel = true; return(false); }, (Action) delegate() { // Special case when adding a new row if (!dialog.IsBatch && state == DataRowState.Added) { // Import the saved row sourceTable.ImportRow(savedVersion.Rows[0]); // Even though nothing needs to be updated, mark it as added so AppliedChanges handled treats it properly RowT newRow = sourceTable.Rows[sourceTable.Rows.Count - 1] as RowT; newRow.SetAdded(); // Set as new target content dialog.TargetContent = newRow; dialog.Content = Dialog_MakeEditVersion <TableT, RowT>(newRow); } // Activate the post applying action if (postApplying != null) { postApplying(); } else { dialog.EndApplyChanges(e); } } }; if (async) { App.CurrentPage.Window.AsyncOperation( delegates[0] as Action, // out-of-ui action delegates[1] as Func <Exception, bool>, // exception handler delegates[2] as Action // in-ui action ); } else { bool exception = false; try { // out-of-ui action, done in ui because async is not required (delegates[0] as Action).Invoke(); } catch (Exception ex) { // exception handler (delegates[1] as Func <Exception, bool>).Invoke(ex); exception = true; } // in-ui action if (!exception) { (delegates[2] as Action).Invoke(); } if (postApplying != null) { postApplying(); } else { dialog.EndApplyChanges(e); } } }