oxyplot icon indicating copy to clipboard operation
oxyplot copied to clipboard

This PlotModel is already in use by some other PlotView control.

Open sunwayking opened this issue 10 years ago • 46 comments

This issue occures at line 165 in PlotViewEx.cs. As my thought, reattaching same plotmodel to the same plotview should not throw this InvalidOperationException showing on title. Then a possible solution is to avoid throwing InvalidOperationException and reattaching plotmodel when this.currentModel.PlotView equals current plotview object(this).

Code modification is here:

private void OnModelChanged()
{
    lock (this.modelLock)
    {
        if (this.currentModel != null)
        {
            ((IPlotModel)this.currentModel).AttachPlotView(null);
        }

        this.currentModel = this.Model;

        if (this.currentModel != null && !Equals(this.currentModel.PlotView, this))
        {
            if (this.currentModel.PlotView != null)
            {
                throw new InvalidOperationException(
                    "This PlotModel is already in use by some other PlotView control.");
            }

            ((IPlotModel)this.ActualModel).AttachPlotView(this);
        }
    }

    this.InvalidatePlot();
}

sunwayking avatar May 30 '15 10:05 sunwayking

I think this use case should never happen. Can you describe your scenario, please.

tibel avatar Jun 28 '15 08:06 tibel

@tibel I experiended those errors using Xamarin.Forms when creating multiple instances of the same ContentPage (including a PlotView) with different data. Xamarin.Forms does a great job in reusing existing UIViewController to save memory, but it can cause OxyPlot to raise this exception.

HippoBaro avatar Jul 01 '15 06:07 HippoBaro

I have moved the check to PlotModel.AttachPlotView() and allow attaching the same plotView again.

tibel avatar Jul 01 '15 08:07 tibel

In OxyPlot.Xamarin.{Android,iOS}.PlotView you also need to clear the Model when disposing. Not sure what the solution is (if needed) on Windows Phone.

    /// <summary>
    /// Dispose the instance.
    /// </summary>
    /// <param name="disposing">Is the instance disposing.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            this.Model = null;
        }

        base.Dispose(disposing);
    }

staylr avatar Aug 11 '15 09:08 staylr

Hello; Currently I use the version " OxyPlot.Xamarin.Forms.2015.1.889 - alpha" ; and I have the same concerns mentioned at the beginning ; are there a solution? and also I have another worry on that same version the plot does not appear at windows phone ? thanks for your help .

omsara avatar Aug 18 '15 14:08 omsara

This occurs also in the OxyPlot.WPF 2015.1.989.0-alpha release

BWouters avatar Sep 17 '15 15:09 BWouters

Can you provide a sample project that shows the issue, please.

tibel avatar Oct 07 '15 09:10 tibel

I added two examples - with PlotViews created by a DataTemplate. It seems to work on Android, but not for Windows Phone.

objorke avatar Oct 13 '15 18:10 objorke

The ItemTemplate demos works on all Xamarin Forms platforms. @sunwayking Can we close this issue?

objorke avatar Oct 20 '15 20:10 objorke

I encountered that problem as well with that code in PlotModel.cs line 772:

        void IPlotModel.AttachPlotView(IPlotView plotView)
        {
            var currentPlotView = this.PlotView;
            if (!object.ReferenceEquals(currentPlotView, null) &&
                !object.ReferenceEquals(plotView, null) &&
                !object.ReferenceEquals(currentPlotView, plotView))
            {
                throw new InvalidOperationException(
                    "This PlotModel is already in use by some other PlotView control.");
            }

            this.plotViewReference = (plotView == null) ? null : new WeakReference(plotView);
        }

My use case is to display the same plot model on different panels and so I would like to instanciate as many views as necessary binded on a single plot model.

The code above prevents that use case, doesn'it? I do not understand why the model is referencing the view. Should not the invalidation be based on some kind of event? Therefore multiple views could use the same model.

tongbong avatar Nov 04 '15 14:11 tongbong

Currently there is a one-to-one relation between the PlotView and its PlotModel (see #112).

tibel avatar Nov 04 '15 18:11 tibel

Yes, a PlotModel can only be used in one PlotView.

Can we close this issue?

objorke avatar Nov 04 '15 18:11 objorke

If this is part of the major refactoring as in #112, then I would say yes.

tongbong avatar Nov 05 '15 07:11 tongbong

Yes :)

objorke avatar Dec 17 '15 13:12 objorke

Example: WpfExamples / PlotModelAlreadyInUse see description in #780 for how to reproduce

tibel avatar Apr 22 '16 19:04 tibel

Same problem with several plotmodel and plotview using a TabControl and MVVM design

This PlotModel is already in use by some other PlotView control

CedreLo avatar Oct 12 '16 13:10 CedreLo

I just worked around the same issue by defining the PlotModel in XAML instead of in VM, so the PlotModel belongs to the view, not the view model. I think that is how oxyplot is "designed", since it is so tightly coupled to the view. You might be able to something similar by moving your PlotModel instance into the view and bind to that and manipulate that from VM, or just go XAML entirely.

angularsen avatar Oct 13 '16 07:10 angularsen

Could you detail how to instance the plotmodel in the view ?

CedreLo avatar Oct 13 '16 08:10 CedreLo

http://docs.oxyplot.org/en/latest/getting-started/hello-wpf-xaml.html

    <Grid>
<!--        <oxy:PlotView Model="{Binding PlotModel}"/>-->
        <oxy:Plot x:Name="_plot" Title="Forces" IsLegendVisible="True" InvalidateFlag="{Binding InvalidateFlag, Delay=20, IsAsync=True}">
            <oxy:Plot.Axes>
                <oxy:TimeSpanAxis StringFormat="s\.ff" Position="Bottom" Title="Time" Key="Time" />
                <oxy:LinearAxis Position="Left" Title="Force" Unit="kg-f" Key="Forces" />
                <oxy:LinearAxis Position="Right" Title="Moment" Unit="N-m" Key="Moment" />
            </oxy:Plot.Axes>
            <oxy:Plot.Annotations>
                <oxy:LineAnnotation Type="Vertical" X="{Binding Path=TimeMarkerValue, Mode=OneWay}" />
            </oxy:Plot.Annotations>
            <oxy:LineSeries Title="Fx" ItemsSource="{Binding ForceX}" YAxisKey="Forces" />
            <oxy:LineSeries Title="Fy" ItemsSource="{Binding ForceY}" YAxisKey="Forces" />
            <oxy:LineSeries Title="Fz" ItemsSource="{Binding ForceZ}" YAxisKey="Forces" />
<!--            <oxy:LineSeries ItemsSource="{Binding MomentX}" YAxisKey="Moment" />-->
<!--            <oxy:LineSeries ItemsSource="{Binding MomentY}" YAxisKey="Moment" />-->
            <oxy:LineSeries Title="Mz" ItemsSource="{Binding MomentZ}" YAxisKey="Moment" />
        </oxy:Plot>

angularsen avatar Oct 13 '16 08:10 angularsen

The InvalidateFlag is changed in VM whenever it needs to redraw the entire thing, such as when new points are added to the series. Similar to calling Invalidate methods on the plot model itself.

angularsen avatar Oct 13 '16 08:10 angularsen

Thanks!!

CedreLo avatar Oct 13 '16 08:10 CedreLo

but this xaml example doesn't work in UWP :-(

deRightDirection avatar Dec 13 '16 19:12 deRightDirection

This might be a bit of a dumb question, but how come there is a 1:1 between the PlotModel and the View? We've been having trouble in our WPF app, using DataTemplates, with this exception. I've been digging and eventually just removed the exception being thrown in PlotModel.cs line 772, as referenced by @tongbong and nothing (at least on the surface) seems to have gone horrifically wrong.

patrickklaeren avatar May 19 '17 20:05 patrickklaeren

What is the reasoning behind this exception? In my app, the PlotModel object is constructed and maintained in the VM, but the view is getting constructed every time the user opens the section of the app, which contains the actual plot. So this exception is thrown every time the user navigates to the plot, then back to the main view and then back again to the plot.

inosik avatar Jul 07 '17 07:07 inosik

Same error on WPF v1.0 The error raise when the aplication is open and connect via desktop remote. Then raise the error: This PlotModel is already in use by some other PlotView control.

en OxyPlot.PlotModel.OxyPlot.IPlotModel.AttachPlotView(IPlotView plotView) en C:\projects\oxyplot\Source\OxyPlot\PlotModel\PlotModel.cs:línea 798 en OxyPlot.Wpf.PlotView.OnModelChanged() en C:\projects\oxyplot\Source\OxyPlot.Wpf\PlotView.cs:línea 153 en OxyPlot.Wpf.PlotView.ModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) en C:\projects\oxyplot\Source\OxyPlot.Wpf\PlotView.cs:línea 140 en System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) en System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) en System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) en System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) en System.Windows.StyleHelper.ApplyTemplatedParentValue(DependencyObject container, FrameworkObject child, Int32 childIndex, FrugalStructList1& childRecordFromChildIndex, DependencyProperty dp, FrameworkElementFactory templateRoot) en System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode(DependencyObject container, FrameworkObject child, Int32 childIndex, FrugalStructList1& childRecordFromChildIndex, Boolean isDetach, FrameworkElementFactory templateRoot) en System.Windows.FrameworkTemplate.InvalidatePropertiesOnTemplate(DependencyObject container, Object currentObject) en System.Windows.FrameworkTemplate.HandleBeforeProperties(Object createdObject, DependencyObject& rootObject, DependencyObject container, FrameworkElement feContainer, INameScope nameScope) en System.Windows.FrameworkTemplate.<>c__DisplayClass45_0.<LoadOptimizedTemplateContent>b__2(Object sender, XamlObjectEventArgs args) en System.Xaml.XamlObjectWriter.OnBeforeProperties(Object value) en System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx) en System.Xaml.XamlObjectWriter.WriteStartMember(XamlMember property) en System.Xaml.XamlWriter.WriteNode(XamlReader reader) en System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)

en System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter) en System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlObjectWriter objectWriter) en System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List1 affectedChildren, UncommonField1 templatedNonFeChildrenField) en System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List1 affectedChildren) en System.Windows.StyleHelper.ApplyTemplateContent(UncommonField1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate) en System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField1 templateDataField, FrameworkElement container) en System.Windows.FrameworkElement.ApplyTemplate() en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.WrapPanel.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) en System.Windows.Controls.ItemsPresenter.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Border.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Control.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) en System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.VirtualizingStackPanel.MeasureChild(IItemContainerGenerator& generator, IContainItemStorage& itemStorageProvider, IContainItemStorage& parentItemStorageProvider, Object& parentItem, Boolean& hasUniformOrAverageContainerSizeBeenSet, Double& computedUniformOrAverageContainerSize, Double& computedUniformOrAverageContainerPixelSize, Boolean& computedAreContainersUniformlySized, IList& items, Object& item, IList& children, Int32& childIndex, Boolean& visualOrderChanged, Boolean& isHorizontal, Size& childConstraint, Rect& viewport, VirtualizationCacheLength& cacheSize, VirtualizationCacheLengthUnit& cacheUnit, Boolean& foundFirstItemInViewport, Double& firstItemInViewportOffset, Size& stackPixelSize, Size& stackPixelSizeInViewport, Size& stackPixelSizeInCacheBeforeViewport, Size& stackPixelSizeInCacheAfterViewport, Size& stackLogicalSize, Size& stackLogicalSizeInViewport, Size& stackLogicalSizeInCacheBeforeViewport, Size& stackLogicalSizeInCacheAfterViewport, Boolean& mustDisableVirtualization, Boolean isBeforeFirstItem, Boolean isAfterFirstItem, Boolean isAfterLastItem, Boolean skipActualMeasure, Boolean skipGeneration, Boolean& hasBringIntoViewContainerBeenMeasured, Boolean& hasVirtualizingChildren) en System.Windows.Controls.VirtualizingStackPanel.MeasureOverrideImpl(Size constraint, Nullable1& lastPageSafeOffset, List1& previouslyMeasuredOffsets, Nullable1& lastPagePixelSize, Boolean remeasure) en System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) en System.Windows.Controls.ItemsPresenter.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Border.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Control.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) en System.Windows.Controls.ScrollContentPresenter.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV) en System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged) en System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV) en System.Windows.Controls.Grid.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.ScrollViewer.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Border.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV) en System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged) en System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV) en System.Windows.Controls.Grid.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV) en System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged) en System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV) en System.Windows.Controls.Grid.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) en System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Border.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Control.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) en System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Border.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV) en System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged) en System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV) en System.Windows.Controls.Grid.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Control.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Grid.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV) en System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged) en System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV) en System.Windows.Controls.Grid.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Grid.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) en System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Border.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Control.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) en System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Control.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Grid.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint) en System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Documents.AdornerDecorator.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Controls.Border.MeasureOverride(Size constraint) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.Window.MeasureOverrideHelper(Size constraint) en System.Windows.Window.MeasureOverride(Size availableSize) en System.Windows.FrameworkElement.MeasureCore(Size availableSize) en System.Windows.UIElement.Measure(Size availableSize) en System.Windows.ContextLayoutManager.UpdateLayout() en System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg) en System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork() en System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks() en System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget) en System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget) en System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) en System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

ProDInfo avatar Jul 11 '17 05:07 ProDInfo

I don't think it has anything to do with remote desktop. It's like I asked, if you maintain the view from the ViewModel and redraw the UI, the plotmodel is in use because the previous view may not have been GC'd or is being cached underlyingly. Also, thanks for that obnoxiously long stack trace.

patrickklaeren avatar Jul 11 '17 05:07 patrickklaeren

I know this is old and done, but until proper refactoring mentioned above is complete. Using PlotModel in a ViewModels and dynamically generating Views (ex. TabControls with DataTemplates) is not possible with out having the exception thrown once in a while.

So I though I would share a "simple" hack work around.

Instantiate this type instead of PlotModel in your VM and the most recent DataTemplate View will be auto attached.

    using System;
    using System.Linq;
    using System.Reflection;
    using OxyPlot;

    /// <summary>
    /// Use this sub implementation of the <see cref="PlotModel"/> if the view will be declared using data template.
    /// Because views will be automatically generated, and new view will be different this causes current version to throw an error.
    /// </summary>
    public class ViewResolvingPlotModel : PlotModel, IPlotModel
    {
        private static readonly Type BaseType = typeof(ViewResolvingPlotModel).BaseType;
        private static readonly MethodInfo BaseAttachMethod = BaseType
            .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
            .Where(methodInfo => methodInfo.IsFinal && methodInfo.IsPrivate)
            .FirstOrDefault(methodInfo => methodInfo.Name.EndsWith(nameof(IPlotModel.AttachPlotView)));

        void IPlotModel.AttachPlotView(IPlotView plotView)
        {
            //because of issue https://github.com/oxyplot/oxyplot/issues/497 
            //only one view can ever be attached to one plotmodel
            //we have to force detach previous view and then attach new one
            if (plotView != null && PlotView != null && !Equals(plotView, PlotView))
            {
                BaseAttachMethod.Invoke(this, new object[] { null });
                BaseAttachMethod.Invoke(this, new object[] { plotView });
            }
            else
            {
                BaseAttachMethod.Invoke(this, new object[] { plotView });
            }
        }
    }

edvinasz avatar Aug 14 '17 18:08 edvinasz

I also commented out the exception being thrown in PlotModel.cs as mentioned by @Inzanit and @tongbong. I'm using WPF targeting .NET 4.0

JohnnyHerms avatar Sep 28 '17 21:09 JohnnyHerms

edvinasz's approach solved my problem. Thank you so much! @edvinasz

xcosmos6 avatar Feb 06 '18 17:02 xcosmos6

Does @edvinasz' solution cause any other issues elsewhere, or could it be added to PlotModel directly?

fuglede avatar May 09 '18 07:05 fuglede