diff --git a/Src/Common/Controls/DetailControls/DataTree.cs b/Src/Common/Controls/DetailControls/DataTree.cs index 9303b46973..fc76ce6d9d 100644 --- a/Src/Common/Controls/DetailControls/DataTree.cs +++ b/Src/Common/Controls/DetailControls/DataTree.cs @@ -154,6 +154,7 @@ public class DataTree : UserControl, IVwNotifyChange, IxCoreColleague, IRefresha bool m_fDoNotRefresh = false; bool m_fPostponedClearAllSlices = false; // Set during ConstructSlices, to suppress certain behaviors not safe at this point. + bool m_postponePropChanged = true; internal bool ConstructingSlices { get; private set; } public List Slices { get; private set; } @@ -527,6 +528,15 @@ public LcmStyleSheet StyleSheet } + public virtual bool OnPostponePropChanged(object commandObject) + { + if ((bool)commandObject == true) + m_postponePropChanged = true; + else + m_postponePropChanged = false; + return true; + } + public void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel) { CheckDisposed(); @@ -557,7 +567,13 @@ public void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel) // because some slice data structures that are being used by the invoker // get disposed by RefreshList (LT-21980, LT-22011). So we postpone calling // RefreshList until the work is done. - this.BeginInvoke(new Action(PostponedRefreshList)); + if (m_postponePropChanged) + { + this.BeginInvoke(new Action(RefreshListAndFocus)); + } else + { + RefreshListAndFocus(); + } } // Note, in LinguaLinks import we don't have an action handler when we hit this. else if (m_cache.DomainDataByFlid.GetActionHandler() != null && m_cache.DomainDataByFlid.GetActionHandler().IsUndoOrRedoInProgress) @@ -584,7 +600,7 @@ public void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel) } } - private void PostponedRefreshList() + private void RefreshListAndFocus() { if (!IsDisposed) { diff --git a/Src/Common/Controls/DetailControls/GhostStringSlice.cs b/Src/Common/Controls/DetailControls/GhostStringSlice.cs index 547b30b74e..fcda37a7d4 100644 --- a/Src/Common/Controls/DetailControls/GhostStringSlice.cs +++ b/Src/Common/Controls/DetailControls/GhostStringSlice.cs @@ -454,7 +454,19 @@ private void SwitchToReal() // Make the real object and set the string property we are ghosting. The final PropChanged // will typically dispose this and create a new string slice whose key is our own key // followed by the flid of the string property. - int hvoNewObj = MakeRealObject(tssTyped); + // To avoid problems, PropChanged must not be postponed (cf. LT-22018). + // Copy m_mediator in case 'this' gets disposed. + Mediator mediator = m_mediator; + int hvoNewObj; + try + { + mediator.SendMessage("PostponePropChanged", false); + hvoNewObj = MakeRealObject(tssTyped); + } + finally + { + mediator.SendMessage("PostponePropChanged", true); + } // Now try to make a suitable selection in the slice that replaces this. RestoreSelection(ich, datatree, parentKey, hvoNewObj, flidStringProp, wsToCreate);