Я использую WPF и .NET 6.0. Мое приложение по сути представляет собой демонстрацию MVVM Джоша Смита с замененной бизнес-логикой. Код графика находится в проекте .NET 6.0, отдельном от приложения. Приложение имеет независимые рабочие области на отдельных вкладках. Я могу открыть несколько вкладок, некоторые с графиками, некоторые без, но если я попытаюсь вернуться на вкладку с графиками, я увижу сообщение об ошибке выше. Когда я пытаюсь вернуться на вкладку с графиками, я вижу, что представления создаются снова, как раз перед тем, как выдается исключение. Я без проблем использую этот же код в приложении .NET Framework 4.7.2.
Мой XAML:
<UserControl x:Class = "DataPlot.Views.BasicTrackView"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:local = "clr-namespace:DataPlot.Views"
xmlns:oxy = "http://oxyplot.org/wpf"
mc:Ignorable = "d"
d:DesignHeight = "450" d:DesignWidth = "800">
<Grid>
<oxy:PlotView x:Name = "Plot" Model = "{Binding PlotModel}" Grid.Column = "1" MinHeight = "{Binding MinimumPlotHeight}">
<oxy:PlotView.DefaultTrackerTemplate>
<ControlTemplate>
<oxy:TrackerControl Position = "{Binding Position}" LineExtents = "{Binding PlotModel.PlotArea}">
<oxy:TrackerControl.Background>
<LinearGradientBrush EndPoint = "0,1">
<GradientStop Color = "#f0e0e0ff" />
<GradientStop Offset = "1" Color = "#f0ffffff" />
</LinearGradientBrush>
</oxy:TrackerControl.Background>
<oxy:TrackerControl.Content>
<TextBlock Text = "{Binding}" Margin = "7" />
</oxy:TrackerControl.Content>
</oxy:TrackerControl>
</ControlTemplate>
</oxy:PlotView.DefaultTrackerTemplate>
</oxy:PlotView>
</Grid>
</UserControl>
Код позади:
public partial class BasicTrackView : UserControl
{
public BasicTrackView()
{
InitializeComponent();
}
}
У меня есть несколько подобных графиков в ItemsControl:
<UserControl x:Class = "DataPlot.Views.TrackContainerView"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:local = "clr-namespace:DataPlot.Views"
xmlns:vm = "clr-namespace:DataPlot.ViewModels"
xmlns:helpers = "clr-namespace:DataPlot.Helpers"
mc:Ignorable = "d"
d:DesignHeight = "450" d:DesignWidth = "800">
<UserControl.Resources>
<DataTemplate DataType = "{x:Type vm:BasicTrackViewModel}">
<local:BasicTrackView/>
</DataTemplate>
<DataTemplate DataType = "{x:Type vm:GenericTrackViewModel}">
<local:GenericTrackView IsActive = "{Binding IsActive}"/>
</DataTemplate>
<DataTemplate DataType = "{x:Type vm:CollapsableTrackViewModel}">
<local:CollapsableTrackView IsActive = "{Binding IsActive}"/>
</DataTemplate>
</UserControl.Resources>
<Grid HorizontalAlignment = "Stretch" VerticalAlignment = "Stretch">
<Grid.RowDefinitions>
<RowDefinition Height = "30"/>
<RowDefinition Height = "*"/>
</Grid.RowDefinitions>
<Label Grid.Row = "0" Content = "Controls?" Width = "60" Height = "25" HorizontalAlignment = "Right" Margin = "0,2,20,2" Grid.Column = "4"
HorizontalContentAlignment = "Center" VerticalContentAlignment = "Center" Background = "LightGray">
<Label.ToolTip>
<ToolTip>
<DockPanel Width = "200" Height = "75">
<TextBox Text = "Zoom: Ctrl + Right Mouse, or
Zoom with mouse wheel
Pan: Right Mouse" AcceptsReturn = "True"/>
</DockPanel>
</ToolTip>
</Label.ToolTip>
</Label>
<ScrollViewer Grid.Row = "1" VerticalScrollBarVisibility = "Auto" HorizontalScrollBarVisibility = "Auto">
<ItemsControl Grid.Row = "1" ItemsSource = "{Binding TrackViewModels}" HorizontalAlignment = "Stretch" VerticalAlignment = "Stretch">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid helpers:GridHelpers.RowCount = "{Binding TrackViewModels.Count}" helpers:GridHelpers.StarRows = "All"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property = "Grid.Row" Value = "{Binding RowIndex}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
Могу ли я что-то сделать, чтобы приложение не пыталось воссоздать уже существующие представления?
Спасибо. Я опубликовал ваше решение в качестве ответа.





Я хотел бы выразить благодарность bigcrazal (в его комментарии) за предоставление простого решения с помощью ссылки на код, предоставленный Эдвинашем. Поскольку ссылки могут испортиться, я приведу код ниже. В своем вопросе я упомянул, что у меня не было проблем с этим кодом в старых проектах .NET Framework 4.7.2. Теперь я считаю, что это потому, что я использовал статические вкладки в своих прошлых приложениях.
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 });
}
}
}
Я видел то же самое, и этот пост на их github очень помог. Я реализовал
ViewResolvingPlotModelи использовал его вместоPlotModelв своей модели представления, и проблема исчезла. Я не уверен, что это будет работать непосредственно в xaml, но это подчеркивает проблему. github.com/oxyplot/oxyplot/issues/497#issuecomment-322268584