public void EndApplyChanges(CancelRoutedEventArgs bargs) { if (bargs.Cancel) { return; } if (bargs.Skip) { if (bargs.CloseDialog) { this.Close(); } return; } // Update final content, if it is null it means it's already been updated if (this.TargetContent != null && this._bindings != null) { foreach (BEData bdata in _bindings) { // Get current val object val = bdata.Obj.GetValue(bdata.Prp); object datacontext = (bdata.Obj as FrameworkElement).DataContext; // Change the data context (bdata.Obj as FrameworkElement).DataContext = this.TargetContent; // Set the value back to the textbox, and update the permanent source bdata.Obj.SetValue(bdata.Prp, val); bdata.Exp.UpdateSource(); // Restore the temp. content (bdata.Obj as FrameworkElement).ClearValue(FrameworkElement.DataContextProperty); } } // Raise the post-apply event, this is for validations and persistence CancelRoutedEventArgs aargs = new CancelRoutedEventArgs(); aargs.RoutedEvent = AppliedChangesEvent; aargs.Source = this; aargs.CloseDialog = bargs.CloseDialog; OnAppliedChanges(aargs); // Close the dialog if necessary if (bargs.CloseDialog && !aargs.Cancel) { this.Close(); } }
public void EndApplyChanges(CancelRoutedEventArgs bargs) { if (bargs.Cancel) { return; } if (bargs.Skip) { if (bargs.CloseDialog) { this.Close(); } return; } // Update final content, if it is null it means it's already been updated if (this.TargetContent != null && this._bindings != null) { // If target is a list, apply changes to all of them IEnumerable targetItems; if (this.TargetContent is IEnumerable) { targetItems = this.TargetContent as IEnumerable; } else { targetItems = new object[] { this.TargetContent } }; ApplyBindingsToItems(targetItems); } // Raise the post-apply event, this is for validations and persistence CancelRoutedEventArgs aargs = new CancelRoutedEventArgs(); aargs.RoutedEvent = AppliedChangesEvent; aargs.Source = this; aargs.CloseDialog = bargs.CloseDialog; OnAppliedChanges(aargs); // Close the dialog if necessary if (bargs.CloseDialog && !aargs.Cancel) { this.Close(); } }
/// <summary> /// /// </summary> public bool Close() { // Raise the confirmation event CancelRoutedEventArgs args = new CancelRoutedEventArgs(); args.RoutedEvent = ClosingEvent; args.Source = this; OnClosing(args); if (args.Cancel) { return(false); } // Don't mark as changed while applying changes this.Content = null; SetValue(TargetContentProperty, null); IsOpen = false; return(true); }
/// <summary> /// /// </summary> protected static void Dialog_AppliedChanges <RowType>(FloatingDialog dialog, string editingDialogTitle, ListView hostListView, int minPosition, CancelRoutedEventArgs e) where RowType : DataRow { // All went well, so just accept changes RowType finalRow = dialog.TargetContent as RowType; DataRowState state = finalRow.RowState; finalRow.Table.AcceptChanges(); (dialog.Content as RowType).AcceptChanges(); // Add to the table if (state == DataRowState.Added) { ObservableCollection <DataRow> items = hostListView.ItemsSource as ObservableCollection <DataRow>; // -2 because we already added the row to the table. We want the position of the last available int newIndex = finalRow.Table.Rows.Count > 1 ? items.IndexOf(finalRow.Table.Rows[finalRow.Table.Rows.Count - 2]) + 1 : minPosition; if (newIndex >= 0) { // Insert a new row to the items only if a new position has been found items.Insert(newIndex, finalRow); hostListView.SelectedIndex = newIndex; hostListView.ScrollIntoView(finalRow); } } if (finalRow is IPropertyChangeNotifier) { (finalRow as IPropertyChangeNotifier).OnAllPropertiesChanged(); } dialog.Title = editingDialogTitle; }
/// <summary> /// /// </summary> protected static void Dialog_AppliedChanges <RowType>(FloatingDialog dialog, string editingDialogTitle, ListView hostListView, CancelRoutedEventArgs e) where RowType : DataRow { Dialog_AppliedChanges <RowType>(dialog, editingDialogTitle, hostListView, 0, 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 <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); } } }
protected static void Dialog_ApplyingChanges <TableType, RowType>(TableType sourceTable, FloatingDialog dialog, MethodInfo saveMethod, CancelRoutedEventArgs e, object[] additionalArgs) where TableType : DataTable, new() where RowType : DataRow { Dialog_ApplyingChanges <TableType, RowType>(sourceTable, dialog, saveMethod, e, additionalArgs, false, null); }
/// <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); } } }
protected static void Dialog_ApplyingChanges <TableT, RowT>(TableT sourceTable, FloatingDialog dialog, MethodInfo saveMethod, CancelRoutedEventArgs e) where TableT : DataTable, new() where RowT : DataRow { Dialog_ApplyingChanges <TableT, RowT>(sourceTable, dialog, saveMethod, e, null, false, null); }
/// <summary> /// /// </summary> public void StartApplyChanges(bool closeDialog) { if (!this.IsOpen) { throw new InvalidOperationException("Dialog is not open"); } // Update source because the binding might not have been activated, so change focus to trigger it this.Focus(); // Validations List <string> errors = new List <string>(); if (_bindings != null) { foreach (BEData bdata in _bindings) { if (bdata.Exp.HasError) { errors.Add(bdata.Exp.ValidationError.ErrorContent as string); } else if (bdata.Exp.ParentBinding.ValidationRules.Count > 0) { foreach (ValidationRule rule in bdata.Exp.ParentBinding.ValidationRules) { // Validate the binding again (just in case) ValidationResult result = rule.Validate(bdata.Obj.GetValue(bdata.Prp), null); if (!result.IsValid) { errors.Add(result.ErrorContent as string); // Trigger a validation error bdata.Exp.UpdateSource(); break; } } } } } // Fail on any validation error if (errors.Count > 0) { string output = string.Empty; foreach (string error in errors) { if (!string.IsNullOrEmpty(error)) { output += error + "\n"; } } MessageBox.Show(output, "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } // Raise the before event, this puts the DataRow in edit mode CancelRoutedEventArgs bargs = new CancelRoutedEventArgs(); bargs.RoutedEvent = ApplyingChangesEvent; bargs.CloseDialog = closeDialog; bargs.Source = this; OnApplyingChanges(bargs); }