【问题标题】:Styling WPF OxyPlot PlotViews in XAML在 XAML 中设置 WPF OxyPlot PlotViews 的样式
【发布时间】:2017-08-20 02:44:15
【问题描述】:

在设置 OxyPlot 绘图视图时,您可以通过各种控件显式定义绘图,或通过绑定到 PlotModel 来设置它。

因此,在第一种情况下,两个 LineSeries 对象的图的 XAML 可能类似于

<oxy:Plot Title="Some plot">
    <oxy:Plot.Axes>
        <oxy:LinearAxis Position="Left" />
        <oxy:LinearAxis Position="Bottom" />
    </oxy:Plot.Axes>
    <oxy:Plot.Series>
        <oxy:LineSeries ItemsSource="{Binding ActualSeriesData1}" DataFieldX="X" DataFieldY="Y"/>
        <oxy:LineSeries ItemsSource="{Binding ActualSeriesData2}" DataFieldX="X" DataFieldY="Y"/>
    </oxy:Plot.Series>
</oxy:Plot>

具有非常薄的视图模型。另一方面,在第二种情况下,我只会有类似

<oxy:PlotView Model="{Binding SomePlotModel}" />

并在视图模型中构建实际绘图。两种设置各有利弊,但我发现当我事先知道我真正想要绘制的内容时,第一种方法通常效果更好,而第二种方法允许对绘图内容进行动态更改。

我的问题如下:对于第一种情况,我知道如何为所有绘图添加一般样式。例如,如果我想让它们看起来像 Seaborn,我会添加类似

<x:Array Type="Color" x:Key="SeabornColors">
    <Color>#4c72b0</Color>
    <Color>#55a868</Color>
    <Color>#c44e52</Color>
    <Color>#8172b2</Color>
    <Color>#ccb974</Color>
    <Color>#64b5cd</Color>
</x:Array>
<Style TargetType="oxy:Plot">
    <Setter Property="PlotAreaBackground" Value="#EBEBF2" />
    <Setter Property="PlotAreaBorderThickness" Value="0" />
    <Setter Property="TitleFont" Value="Segoe UI" />
    <Setter Property="TitleFontWeight" Value="Normal" />
    <Setter Property="DefaultColors" Value="{StaticResource SeabornColors}"/>
</Style>
<Style TargetType="oxy:LinearAxis">
    <Setter Property="TicklineColor" Value="White" />
    <Setter Property="MajorGridlineColor" Value="White" />
    <Setter Property="MinorGridlineColor" Value="White" />
    <Setter Property="ExtraGridlineColor" Value="White" />
    <Setter Property="AxislineColor" Value="White" />
    <Setter Property="TitleColor" Value="Black" />
    <Setter Property="TextColor" Value="Black" />
    <Setter Property="Font" Value="Segoe UI" />
    <Setter Property="TitleFont" Value="Segoe UI" />
    <Setter Property="TickStyle" Value="None" />
    <Setter Property="MajorGridlineStyle" Value="Solid" />
</Style>

致我的ResourceDictionary。如何在第二种情况下达到相同的效果,即使用oxy:PlotView?我可以使用&lt;Style TargetType="oxy:PlotView" /&gt; 设置一些常规样式属性,但是我将如何设置所有LineSeries 的样式,比如Series 中的Model 中的Model 中的PlotView

【问题讨论】:

  • 我也遇到过同样的问题,我能够解决的唯一方法是使用后面的代码来设置 PlotModels 上的属性。它仍然将设计与逻辑分开,但遗憾的是没有使用 XAML 或样式。
  • @Herman:有没有一种直接的方法可以适用于应用程序中的所有 PlotModel?这是将其设置为样式的好处之一。
  • 我能想到的最好方法是为每种样式创建一个以 PlotModel 作为参数的方法,然后遍历所有绘图模型并为每个 PlotModel 调用该方法。从理论上讲,您可以在一个窗口中找到所有 PlotViews 并提取 PlotModel,但在我的情况下,我的 ViewModel 已经有一个绘图模型数组,因此更简单。
  • 我认为你的问题不够具体。每当使用 PlotView / PlotModel / Plot 时,没有什么能阻止您重新使用 XAML 资源,无论是作为 StaticResource 还是通过代码隐藏中的 Application.Current.Resources["SomeResourceKey"]。但请记住,可能存在不兼容的类型,例如,ColorOxyColor 之间。而且在OxyPlot.Wpf.LinearAxisOxyPlot.Axes.LinearAxis之间......
  • @RobL 取决于项目的类型;因为这个特别是关于 WPF,我们会做xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"。我不知道在Xamarin.Forms 中调用了哪些相关类型,但如果它没有Plot,我猜你会使用你在Xamarin.Forms 中使用的任何东西。

标签: c# .net wpf xaml oxyplot


【解决方案1】:

我没有通过所有的 cmets,但其中一些似乎已经包含解决方案的链接。我有一个示例,我正在使用 MVVM 方法并更改这些设置。它应该有帮助:

在 MainWindow.xaml 中:

<oxy:PlotView Name="TestView" Model="{Binding plotModel}" Grid.Row="0" Grid.Column="1" />

在我的 MainWindowViewModel.cs 中:

private PlotModel m_plotModel;
public PlotModel plotModel
{
    get { return m_plotModel; }
    set => SetAndRaisePropertyChanged(ref m_plotModel, value);
}

public UserControlOscilloViewModel()
{
    var signalAxis = new CategoryAxis()
    {
        Position = AxisPosition.Left,
        Minimum = 0,
        MinimumMinorStep = 1,
        AbsoluteMinimum = 0,
        TicklineColor = OxyColors.Transparent,
    };
    var timeAxis = new LinearAxis()
    {
        Position = AxisPosition.Bottom,
        Minimum = 0,
        MinimumMajorStep = 1,
        AbsoluteMinimum = 0,
    };

    plotModel = new PlotModel();            
    plotModel.Axes.Add(signalAxis);
    plotModel.Axes.Add(timeAxis);
}

然后,当您刷新模型时,如果需要,您可以像这样访问您的轴:

CategoryAxis signalAxis = (CategoryAxis)plotModel.Axes.ElementAt(0);
LinearAxis timeAxis = (LinearAxis)plotModel.Axes.ElementAt(1);

并像这样添加系列:

var series = new LineSeries
{
    Color = OxyColors.SeaShell,
    LineStyle = LineStyle.Dash
};
foreach (DataPoint p in ListOfPoints)
{
    series.Points.Add(p);
}
plotModel.Series.Add(series);
plotModel.InvalidatePlot(true);

我并没有完全解决您的问题,但我认为您可以通过这样做访问所有需要的对象/成员。我还简化了我的代码以提高清晰度,我希望这样做时我没有破坏任何东西......

【讨论】:

  • 嗯,是的,我不确定我是否跟随;我遇到的主要问题是应用程序中所有PlotModels 的样式;为个人设置样式很简单,最终我选择了@Herman 建议的或多或少的解决方案,创建了一种方法来设置给定PlotModel 的样式,并确保每个相关的都调用该方法。不理想,但它可以完成工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多