Hi,
Our customer encountered exception in xamSpreadsheet control. Based on description customer loaded this control view left it opened. After an hour or more he tried to access same application control and got exception with fallowing stack trace:
System.NotSupportedException: Workbooks can not have multiple owners bei Infragistics.Documents.Excel.Workbook.RegisterOwner(IWorkbookOwner owner) bei Infragistics.Controls.Grids.Core.Spreadsheet.OnWorkbookChanged(Workbook oldWorkbook, Workbook newWorkbook) bei Infragistics.Controls.Grids.Core.Spreadsheet.set_Workbook(Workbook value) bei Infragistics.Controls.Grids.XamSpreadsheet.<>c.<.cctor>b__365_42(XamSpreadsheet c, Object v) bei Infragistics.Controls.Grids.XamSpreadsheet.SetInnerProperty[T](T d, Object newValue, Action`2 setter, String propertyName) bei Infragistics.Controls.Grids.XamSpreadsheet.<>c.<.cctor>b__365_41(DependencyObject d, DependencyPropertyChangedEventArgs e) bei System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) bei System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) bei System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) bei System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) bei System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal) bei System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value) bei Infragistics.Controls.Grids.XamSpreadsheet.set_Workbook(Workbook value) bei EafClient.Editor.Core.Workbooks.SpreadsheetControl.SpreadsheetWorkbook.ApplyTo(XamSpreadsheet spreadsheetControl) in D:\TfsBuildAgent2017\_work\278\s\Source\Implementation\EafClient.Editor.Core\Workbooks\SpreadsheetControl\SpreadsheetWorkbook.cs:Zeile 97. bei EafClient.Editor.CellAutomation.EquipmentDictionary.Views.SpecificBehaviors.EquipmentDictionaryWorkbookBehavior.WorkbookDataChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) in D:\TfsBuildAgent2017\_work\278\s\Source\Implementation\EafClient.Editor.CellAutomation\EquipmentDictionary\Views\SpecificBehaviors\EquipmentDictionaryWorkbookBehavior.cs:Zeile 155. bei System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) bei System.Windows.Freezable.OnPropertyChanged(DependencyPropertyChangedEventArgs e) bei System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) bei System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) bei System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue) bei System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange) bei System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange) bei System.Windows.Data.BindingExpression.Activate(Object item) bei System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt) bei System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance) bei MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance) bei MS.Internal.Data.DataBindEngine.Run(Object arg) bei MS.Internal.Data.DataBindEngine.OnLayoutUpdated(Object sender, EventArgs e) bei System.Windows.ContextLayoutManager.fireLayoutUpdateEvent() bei System.Windows.ContextLayoutManager.UpdateLayout() bei System.Windows.UIElement.UpdateLayout() bei Infragistics.Windows.DataPresenter.GridUtilities.ProcessAsyncInvalidationsImpl() bei Infragistics.Windows.DataPresenter.GridUtilities.ProcessAsyncInvalidations()
Our code involved in stack trace just monitoring changes and then reapplying back the workbook. Here is line 155 from our code with ApplyTo:
var behaviorInstance = d as EquipmentDictionaryWorkbookBehavior; (e.NewValue as IWorkbook)?.ApplyTo(behaviorInstance?.Spreadsheet);
And then setting back (line 97 in SpreadsheetWorkbook class):
public void ApplyTo(XamSpreadsheet spreadsheetControl) => spreadsheetControl.Workbook = mWorkbook;
The workbook behavior is grabbing active spreadsheet:
private XamSpreadsheet Spreadsheet => AssociatedObject.SpreadSheet;book;
What could cause this error if we use only 1 control in our application? No other user should be able to access this application during away time.
I don't know if it could be related, but this is Virtual PC and during this time auto lock of windows is enabled.
Hi Andrew,
I've tried to check the Load event on our side and it is dead end there since like I wrote before it has no more callers from our code. So can't investigate there. However, as a next step I've added logging to the DockPanel control containing the spreadsheet control which is reloaded and observed that two same instances created of same and running together during raised with event LayoutUpdated. So after session reconnect two spreadsheet controls looks like running with different hash codes while before only 1 was running.
I've tried to create sample application based on our control path but I got stuck on view display in tab page (based on this link). I am attaching my almost completed project:
SpreadsheetOwnerErrorSampleV3.zip
Please help to resolve fallowing issue: selecting "Test 1" or "Test 2" should open new tab in main region and all content is created correctly but it is not displayed in the TabGroupPane. Hopefully this simple application will reproduce the original problem on my Remote Desktop PC once this done. At the moment it is still missing one additional spreadsheet behavior which is setting saved workbook and causing original exception so I should be close to completion.
Hello Tomas,
The sample project I tried did not use a XamDockManager or a remote desktop session, as I was awaiting a more concrete set of reproduction steps from your end or a sample project that reproduces it.
Your mention of the XamDockManager a couple of updates ago only sparked the idea in my mind that you may have multiple instances of the XamSpreadsheet bound to the same instance of the Excel Workbook in this case, and so to test that, I simply put two XamSpreadsheet controls into a WPF Window and assigned a single Workbook to both of them. This reproduced the exception you are seeing, but very likely not in the same route that you are currently doing.
I am curious to know if perhaps something that you could use as a workaround in this case would be to use a flag that determines whether or not a particular Workbook has already been assigned to a XamSpreadsheet or not as this could potentially prevent your code that is assigning the Workbook to a XamSpreadsheet instance from firing again for a different XamSpreadsheet and the same Workbook?
Something that might be worth checking as well is the code-path that is followed when this exception happens. Where in your code are you trying to apply the Workbook to a XamSpreadsheet instance? For example, is it happening in a Loaded event or something along those lines?
Please let me know if you have any other questions or concerns on this matter.
Can you provide your sample application? I would like to try to adapt to my known scenario with single scenario of this control and check if problem still persist on RDP session.
During analysis I noticed that other views reloaded same way as this one but they don't have such a side effects like spread sheet control. Based on stack trace in my very first called view no other our views are involved, thus still causing problem understanding the problem. The stack trace is quite long and it involves mainly Windows calls however few related to Infragistics:
at EafClient.Editor.CellAutomation.EquipmentDictionary.Views.EquipmentDictionaryEditorView..ctor() in D:\_PROJECTS\EAF_MAINT\EAF Mango\v3.x_Maint\Implementation\EafClient.Editor.CellAutomation\EquipmentDictionary\Views\EquipmentDictionaryEditorView.xaml.cs:line 23 at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) at System.Activator.CreateInstance(Type type, Object[] args) ... at Infragistics.Windows.DockManager.SplitPane.MeasureOverride(Size availableSize) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at Infragistics.Windows.DockManager.DocumentContentHostPanel.MeasureOverride(Size availableSize) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) ... at System.Windows.UIElement.Measure(Size availableSize) at Infragistics.Windows.DockManager.DockManagerPanel.MeasureOverride(Size availableSize) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) ... at System.Windows.ContextLayoutManager.UpdateLayout() at System.Windows.UIElement.UpdateLayout() at Infragistics.Windows.DataPresenter.GridUtilities.ProcessAsyncInvalidationsImpl() at Infragistics.Windows.DataPresenter.GridUtilities.ProcessAsyncInvalidations() at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) ....
By the way, have you tried your sample application using fallowing steps:
Thanks for very descriptive definition of rootcause as well as time spent on reproduction what I was suspecting. I will try to determine why the control is reloaded during reconnect. Our application is using only 1 control in same editor but something is resetting the control during RDP connection event and resulting in strange behavior.
I have been running a XamSpreadsheet application against our internal source code to see what the process is for the RegisterOwner issue that you are seeing, and it appears that when the XamSpreadsheet’s Workbook property changes, we check for an old workbook, and if one exists, clear its Undo history and unregister its owner. Then, we register an owner for the new one. An exception is thrown if the cached owner for the Workbook already exists, and that is the only way that this exception happens.
The “owner” that is created in this case is an instance of WeakWorkbookOwner, and it is used primarily in transaction histories for undo operations in the Workbook for usage within the XamSpreadsheet.
The XamDockManager part of this made me think of what could potentially cause this, and I tested the scenario in which there are multiple instances of the XamSpreadsheet with the same instance of the Workbook assigned. In doing so, I reproduced the exception you are seeing, which leads me to believe that somewhere in your application, a new instance of XamSpreadsheet is getting created and has the same Workbook assigned to it, which is not a supported action. Perhaps this information will help you to track down the exception in your application?