/// <summary> /// Saves the specified item in the list. /// </summary> /// <param name="index">Index of item to be saved.</param> /// <param name="delete">true if the item should be deleted.</param> protected virtual async Task SaveItemAsync(int index, bool delete) { T item = this[index]; var handleBusy = false; if ((item.IsDeleted || delete) || (item.IsValid && item.IsDirty)) { T savable = item; // attempt to clone object ICloneable cloneable = savable as ICloneable; if (cloneable != null) { savable = (T)cloneable.Clone(); MethodCaller.CallMethodIfImplemented(item, "MarkBusy"); handleBusy = true; } // commit all changes int editLevel = savable.EditLevel; for (int tmp = 1; tmp <= editLevel; tmp++) { savable.AcceptChanges(editLevel - tmp, false); } if (delete) { savable.Delete(); } Exception error = null; T result = default(T); var dp = ApplicationContext.CreateInstance <DataPortal <T> >(); try { result = await dp.UpdateAsync((T)savable); } catch (AggregateException ex) { if (ex.InnerExceptions.Count > 0) { error = ex.InnerExceptions[0]; } else { error = ex; } } catch (Exception ex) { error = ex; } finally { if (handleBusy) { MethodCaller.CallMethodIfImplemented(item, "MarkIdle"); } } // update index - this may have changed under the duration of async call index = IndexOf(item); if (error == null && result != null) { if (savable.IsDeleted) { //SafeRemoveItem will raise INotifyCollectionChanged event SafeRemoveItem(index); } else { for (int tmp = 1; tmp <= editLevel; tmp++) { result.CopyState(tmp, false); } SafeSetItem(index, result); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, this[index], index)); } item.SaveComplete(result); OnSaved(result, null); } else { item.SaveComplete(item); OnSaved(item, error); } } }
/// <summary> /// Saves the specified item in the list. /// </summary> /// <param name="index"> /// Index of the item to be saved. /// </param> /// <remarks> /// This method properly saves the child item, /// by making sure the item in the collection /// is properly replaced by the result of the /// Save() method call. /// </remarks> public virtual void SaveItem(int index) { T item = this[index]; var handleBusy = false; if (item.IsDeleted || (item.IsValid && item.IsDirty)) { T savable = item; // attempt to clone object ICloneable cloneable = savable as ICloneable; if (cloneable != null) { savable = (T)cloneable.Clone(); MethodCaller.CallMethodIfImplemented(item, "MarkBusy"); handleBusy = true; } // commit all changes int editLevel = savable.EditLevel; for (int tmp = 1; tmp <= editLevel; tmp++) { savable.AcceptChanges(editLevel - tmp, false); } // save object DataPortal <T> dp = new DataPortal <T>(); dp.UpdateCompleted += (o, e) => { if (handleBusy) { MethodCaller.CallMethodIfImplemented(item, "MarkIdle"); } if (e.Error == null) { T result = e.Object; if (item.IsDeleted) { //SafeRemoveItem will raise INotifyCollectionChanged event SafeRemoveItem(index); } else { for (int tmp = 1; tmp <= editLevel; tmp++) { result.CopyState(tmp, false); } SafeSetItem(index, result); #if SILVERLIGHT //Because SL Data Grid does not support replace action. // we have to artificially raise remove/insert events OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index)); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, this[index], index)); #else OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, result, item)); #endif } #if SILVERLIGHT item.SaveComplete(result, null, null); #else item.SaveComplete(result); #endif OnSaved(result, null); } else { #if SILVERLIGHT item.SaveComplete(item, e.Error, null); #else item.SaveComplete(item); #endif OnSaved(item, e.Error); } }; dp.BeginUpdate(savable); } }