OxyPlot是开源的Chart插件,支持WPF和WinForm,相比于Devpress、SCIChart、Toolkit、InteractiveDataDisplay.WPF、Lightningchart个人感觉更加完善和清楚,也不收费。
OxyPlot的实例Demo、可移植库可以下载链接(已上传): link.
可以根据ExampleLibrary下的Examples来改写自己的所有功能。
本文实现了以下示波器功能:
1)双示波器显示
2)参数选择
3)参数显示位置
4)X轴测量
5)Y轴单波形及多波形测量
6)双示波器同步缩放
7)X缩放选择
8)Y缩放选择
9)自由缩放选择
10)图表回原
11) 示波器操作快捷键
<Window
x:Class="ch10_Scope.DoubleOxyPlotWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ch10_Scope"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:oxyplot="http://oxyplot.org/wpf"
Title="DoubleOxyPlotWindow"
Width="1000"
Height="800"
mc:Ignorable="d">
<Window.Resources>
<ResourceDictionary>
<!--<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/DCMotorControlSystem;component/Styles/Button.xaml" />
<ResourceDictionary Source="pack://application:,,,/DCMotorControlSystem;component/Styles/ComboBox.xaml" />
</ResourceDictionary.MergedDictionaries>-->
<Style x:Key="TextBlockStyle" TargetType="TextBlock">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontSize" Value="{Binding TextFontSize}" />
</Style>
<Style x:Key="TextBoxStyle" TargetType="TextBox">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="{Binding TextFontSize}" />
</Style>
<Style x:Key="CheckBoxStyle" TargetType="CheckBox">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<ContextMenu x:Key="ContextMenu1">
<MenuItem Command="{Binding Scope1ResetTableCommand}" Header="图表回原" />
<Separator />
<MenuItem Command="{Binding Scope1AutoZoomCommand}" Header="自由收缩" />
<Separator />
<MenuItem Command="{Binding Scope1XAxisZoomCommand}" Header="X轴缩放" />
<Separator />
<MenuItem Command="{Binding Scope1YAxisZoomCommand}" Header="Y轴缩放" />
<Separator />
<!--<MenuItem Command="{Binding XXAxisZoomCommand}" Header="XX轴同步缩放" />-->
</ContextMenu>
<ContextMenu x:Key="ContextMenu2">
<MenuItem Command="{Binding Scope2ResetTableCommand}" Header="图表回原" />
<Separator />
<MenuItem Command="{Binding Scope2AutoZoomCommand}" Header="自由收缩" />
<Separator />
<MenuItem Command="{Binding Scope2XAxisZoomCommand}" Header="X轴缩放" />
<Separator />
<MenuItem Command="{Binding Scope2YAxisZoomCommand}" Header="Y轴缩放" />
<Separator />
<!--<MenuItem Command="{Binding XXAxisZoomCommand}" Header="XX轴同步缩放" />-->
</ContextMenu>
<local:VisibilityToCheckedConverter x:Key="VisibilityToCheckedConverter" />
</ResourceDictionary>
</Window.Resources>
<Grid Name="gdScope">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<oxyplot:PlotView
Name="MyPlotView1"
ContextMenu="{StaticResource ContextMenu1}"
Model="{Binding PlotViewModel1}">
<oxyplot:PlotView.DefaultTrackerTemplate>
<ControlTemplate>
<oxyplot:TrackerControl
Margin="0"
Background="LightGray"
BorderBrush="Red"
BorderEdgeMode="Unspecified"
BorderThickness="1"
CornerRadius="8"
Distance="0"
Foreground="Black"
LineExtents="{Binding PlotViewModel1.PlotArea}"
Opacity="0.8"
Position="{Binding Position}"
ShowPointer="False">
<oxyplot:TrackerControl.Content>
<TextBlock Margin="7" Text="{Binding}" />
</oxyplot:TrackerControl.Content>
</oxyplot:TrackerControl>
</ControlTemplate>
</oxyplot:PlotView.DefaultTrackerTemplate>
</oxyplot:PlotView>
<oxyplot:PlotView
Name="MyPlotView2"
Grid.Row="1"
ContextMenu="{StaticResource ContextMenu2}"
Model="{Binding PlotViewModel2}">
<oxyplot:PlotView.DefaultTrackerTemplate>
<ControlTemplate>
<oxyplot:TrackerControl
Margin="0"
Background="LightGray"
BorderBrush="Red"
BorderEdgeMode="Unspecified"
BorderThickness="1"
CornerRadius="8"
Distance="0"
Foreground="Black"
LineExtents="{Binding PlotViewModel2.PlotArea}"
Opacity="0.8"
Position="{Binding Position}"
ShowPointer="False">
<oxyplot:TrackerControl.Content>
<TextBlock Margin="7" Text="{Binding}" />
</oxyplot:TrackerControl.Content>
</oxyplot:TrackerControl>
</ControlTemplate>
</oxyplot:PlotView.DefaultTrackerTemplate>
</oxyplot:PlotView>
<Border Grid.RowSpan="2" Grid.Column="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="1.5*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<CheckBox
Name="ckb_Scope"
Grid.ColumnSpan="3"
Click="ckb_Scope_Click"
Content="显示双示波器"
IsChecked="True"
Style="{StaticResource CheckBoxStyle}" />
<!-- 颜色标识 -->
<TextBox
Grid.Row="1"
Margin="10"
Background="Red"
IsReadOnly="True" />
<TextBox
Grid.Row="2"
Margin="10"
Background="Purple"
IsReadOnly="True" />
<TextBox
Grid.Row="3"
Margin="10"
Background="Blue"
IsReadOnly="True" />
<TextBox
Grid.Row="4"
Margin="10"
Background="Green"
IsReadOnly="True" />
<!-- 显示选择 -->
<ComboBox
Name="ComboBoxS1ShowConfig"
Grid.Row="1"
Grid.Column="1"
Width="100"
SelectedItem="{Binding S1ShowConfigSelected, Mode=TwoWay}" />
<ComboBox
Name="ComboBoxS2ShowConfig"
Grid.Row="2"
Grid.Column="1"
Width="100"
SelectedItem="{Binding S2ShowConfigSelected, Mode=TwoWay}" />
<ComboBox
Name="ComboBoxS3ShowConfig"
Grid.Row="3"
Grid.Column="1"
Width="100"
SelectedItem="{Binding S3ShowConfigSelected, Mode=TwoWay}" />
<ComboBox
Name="ComboBoxS4ShowConfig"
Grid.Row="4"
Grid.Column="1"
Width="100"
SelectedItem="{Binding S4ShowConfigSelected, Mode=TwoWay}" />
<!-- 显示参数选择 -->
<ComboBox
Name="ComboBoxS1ShowValueConfig"
Grid.Row="1"
Grid.Column="2"
Width="150"
ItemsSource="{Binding S1ShowValueConfigList}"
SelectedItem="{Binding S1ShowValueConfigSelected}" />
<ComboBox
Name="ComboBoxS2ShowValueConfig"
Grid.Row="2"
Grid.Column="2"
Width="150"
ItemsSource="{Binding S2ShowValueConfigList}"
SelectedItem="{Binding S2ShowValueConfigSelected}" />
<ComboBox
Name="ComboBoxS3ShowValueConfig"
Grid.Row="3"
Grid.Column="2"
Width="150"
ItemsSource="{Binding S3ShowValueConfigList}"
SelectedItem="{Binding S3ShowValueConfigSelected}" />
<ComboBox
Name="ComboBoxS4ShowValueConfig"
Grid.Row="4"
Grid.Column="2"
Width="150"
ItemsSource="{Binding S4ShowValueConfigList}"
SelectedItem="{Binding S4ShowValueConfigSelected}" />
<!-- 采样时长 -->
<TextBlock
Grid.Row="5"
Grid.ColumnSpan="2"
Margin="10"
FontSize="{Binding TextFontSize}"
Style="{StaticResource TextBlockStyle}"
Text="采样时长[s]:" />
<TextBox
Grid.Row="5"
Grid.Column="2"
Margin="10"
FontSize="{Binding TextFontSize}"
Style="{StaticResource TextBoxStyle}"
Text="" />
<!-- 采样周期 -->
<TextBlock
Grid.Row="6"
Grid.ColumnSpan="2"
Margin="10"
FontSize="{Binding TextFontSize}"
Style="{StaticResource TextBlockStyle}"
Text="采样周期[ms]:" />
<TextBox
Grid.Row="6"
Grid.Column="2"
Margin="10"
FontSize="{Binding TextFontSize}"
Style="{StaticResource TextBoxStyle}"
Text="" />
<!-- 触发源 -->
<TextBlock
Grid.Row="7"
Grid.ColumnSpan="2"
Margin="10"
FontSize="{Binding TextFontSize}"
Style="{StaticResource TextBlockStyle}"
Text="触发源:" />
<ComboBox
Name="ComboBoxScopeToggleSource"
Grid.Row="7"
Grid.Column="2"
Width="150">
<ComboBoxItem Content="Current" />
<ComboBoxItem Content="Speed" />
<ComboBoxItem Content="Position" />
</ComboBox>
<!-- 触发值 -->
<TextBlock
Grid.Row="8"
Grid.ColumnSpan="2"
Margin="10"
FontSize="{Binding TextFontSize}"
Style="{StaticResource TextBlockStyle}"
Text="触发值:" />
<TextBox
Grid.Row="8"
Grid.Column="2"
Margin="10"
FontSize="{Binding TextFontSize}"
Style="{StaticResource TextBoxStyle}"
Text="" />
<!-- 触发类型 -->
<TextBlock
Grid.Row="9"
Grid.ColumnSpan="2"
Margin="10"
FontSize="{Binding TextFontSize}"
Style="{StaticResource TextBlockStyle}"
Text="触发类型:" />
<ComboBox
Name="ComboBoxScopeToggleType"
Grid.Row="9"
Grid.Column="2"
Width="150">
<ComboBoxItem Content="Current" />
<ComboBoxItem Content="Speed" />
<ComboBoxItem Content="Position" />
</ComboBox>
<!-- 触发位置 -->
<TextBlock
Grid.Row="10"
Grid.ColumnSpan="2"
Margin="10"
FontSize="{Binding TextFontSize}"
Style="{StaticResource TextBlockStyle}"
Text="触发位置[%]:" />
<TextBox
Grid.Row="10"
Grid.Column="2"
Margin="10"
FontSize="{Binding TextFontSize}"
Style="{StaticResource TextBoxStyle}"
Text="" />
<Grid Grid.Row="11" Grid.ColumnSpan="3">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button
Grid.Column="0"
Margin="10"
FontSize="{Binding TextFontSize}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="0,0,10,0"
FontFamily="../../../Resources/Fonts/#iconfont"
Foreground="White"
Text="" />
<TextBlock Foreground="White" Text="应用配置" />
</StackPanel>
</Button.Content>
</Button>
<Button
Grid.Column="1"
Margin="10"
FontSize="{Binding TextFontSize}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="0,0,10,0"
FontFamily="../../../Resources/Fonts/#iconfont"
Foreground="White"
Text="" />
<TextBlock Foreground="White" Text="保存数据" />
</StackPanel>
</Button.Content>
</Button>
<Button
Grid.Column="2"
Margin="10"
FontSize="{Binding TextFontSize}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="0,0,10,0"
FontFamily="../../../Resources/Fonts/#iconfont"
Foreground="White"
Text="" />
<TextBlock Foreground="White" Text="导入数据" />
</StackPanel>
</Button.Content>
</Button>
<Button
x:Name="ReFlashData"
Grid.Column="3"
Margin="10"
Command="{Binding ReFashDataCommand}"
FontSize="{Binding TextFontSize}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="0,0,10,0"
FontFamily="../../../Resources/Fonts/#iconfont"
Foreground="White"
Text="" />
<TextBlock Foreground="Black" Text="刷新图表" />
</StackPanel>
</Button.Content>
</Button>
</Grid>
</Grid>
</Border>
</Grid>
</Window>
using OxyPlot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace ch10_Scope
{
///
/// DoubleOxyPlotWindow.xaml 的交互逻辑
///
public partial class DoubleOxyPlotWindow : Window
{
List<string> vs = new List<string>()
{
"None","Scope 1","Scope 2"
};
List<string> vs1 = new List<string>()
{
"None","Scope 1"
};
public DoubleOxyPlotWindow()
{
InitializeComponent();
var myController1 = new PlotController();
MyPlotView1.Controller = myController1;
//绑定鼠标进入事件到显示Tracker命令;
myController1.BindMouseEnter(PlotCommands.HoverPointsOnlyTrack);
//禁用鼠标右键调用Pan命令
//myController.BindMouseDown(OxyMouseButton.Right,OxyModifierKeys.None,);
var myController2 = new PlotController();
MyPlotView2.Controller = myController2;
//绑定鼠标进入事件到显示Tracker命令;
myController2.BindMouseEnter(PlotCommands.HoverPointsOnlyTrack);
//禁用鼠标右键调用Pan命令
//myController.BindMouseDown(OxyMouseButton.Right,OxyModifierKeys.None,);
//myController2.BindMouseDown(OxyMouseButton.Left, new DelegatePlotCommand(
// (view, controller, args) =>
// controller.AddMouseManipulator(view, new WpbTrackerManipulator1(view), args)));
this.ComboBoxS1ShowConfig.ItemsSource = vs;
this.ComboBoxS1ShowConfig.SelectedIndex = 0;
this.ComboBoxS2ShowConfig.ItemsSource = vs;
this.ComboBoxS2ShowConfig.SelectedIndex = 0;
this.ComboBoxS3ShowConfig.ItemsSource = vs;
this.ComboBoxS3ShowConfig.SelectedIndex = 0;
this.ComboBoxS4ShowConfig.ItemsSource = vs;
this.ComboBoxS4ShowConfig.SelectedIndex = 0;
this.DataContext = new DoubleOxyPlotWindowViewModel();
}
private void ckb_Scope_Click(object sender, RoutedEventArgs e)
{
if (ckb_Scope.IsChecked == true)//显示双示波器
{
MyPlotView1.SetValue(Grid.RowSpanProperty,