欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

在WPF中使用Winform中自带的画图控件Chart,模拟动态更新数据

程序员文章站 2024-02-16 10:49:28
...

一、如何在WPF中使用Chart控件

1、添加引用

右键项目引用-添加引用,在程序集中选择下图三个东东
在WPF中使用Winform中自带的画图控件Chart,模拟动态更新数据

2、添加命名空间
xmlns:Wchart="clr-namespace:System.Windows.Forms.DataVisualization.Charting;assembly=System.Windows.Forms.DataVisualization"
3、引用

注意要放在WindowsFormsHost标签内部

<WindowsFormsHost Grid.Row="2">
	<Wchart:Chart x:Name="ChartPlot"/>
</WindowsFormsHost>

二、代码

先上最终的效果图,如下图,可选择图中显示的点数,以及更新速度。
在WPF中使用Winform中自带的画图控件Chart,模拟动态更新数据

1、布局设计
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="50"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left">
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
            <RadioButton Name="rbtn_highspeed" Content="100ms" Style="{StaticResource rabtn}" Click="rbtn_highspeed_Click"/>
            <RadioButton Name="rbtn_lowspeed" Content="500ms" IsChecked="True" Style="{StaticResource rabtn}" Click="rbtn_lowspeed_Click"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
            <RadioButton Name="rbtn_manypoint" Content="50点" IsChecked="True" Style="{StaticResource rabtn}" Click="rbtn_manypoint_Click"/>
            <RadioButton Name="rbtn_littlepoint" Content="20点" Style="{StaticResource rabtn}" Click="rbtn_littlepoint_Click"/>
        </StackPanel>
        <Button Name="btn_start" Content="开始" Margin="10,1" Click="btn_start_Click"/>
    </StackPanel>
    <WindowsFormsHost Grid.Row="2">
        <Wchart:Chart x:Name="ChartPlot"/>
    </WindowsFormsHost>
</Grid>

rabtn是自定义的一个RadioButton样式资源文件,感兴趣的可以看看(不看也没影响)

<Style x:Key="rabtn" TargetType="RadioButton">
  <Setter Property="Template">
      <Setter.Value>
          <ControlTemplate TargetType="RadioButton">
              <Border>
                  <Grid Background="Transparent">
                      <Grid.ColumnDefinitions>
                          <ColumnDefinition Width="20"/>
                          <ColumnDefinition Width="Auto"/>
                      </Grid.ColumnDefinitions>
                      <Rectangle Name="rec" Grid.Column="0" Width="15" Height="15" 
                                 Stroke="Black" Fill="White"/>
                      <ContentPresenter Grid.Column="1" VerticalAlignment="Center" Margin="5,1"/>
                  </Grid>
              </Border>
              <ControlTemplate.Triggers>
                  <Trigger Property="IsChecked" Value="True">
                      <Setter TargetName="rec" Property="Fill" Value="RoyalBlue"/>
                      <Setter TargetName="rec" Property="Stroke" Value="Transparent"/>
                  </Trigger>
              </ControlTemplate.Triggers>
          </ControlTemplate>
      </Setter.Value>
  </Setter>
</Style>
2、逻辑实现
public partial class MainWindow : Window
{
    private ChartArea AREA = new ChartArea() { Name = "Line" };             // 画图区域
    private Series SERIES = new Series();                                   // 一条折线
    private Legend LEGEND = new Legend();                                   // 一个图例
    private System.Timers.Timer timer = new System.Timers.Timer();          // 定时器
    private int INTERVAL = 500;                                             // 定时器时间
    private int MAXPLOT = 100;                                              // 图中最多点数
    
    public MainWindow()
    {
        InitializeComponent();

        // area样式设置
        AREA.AxisX.Enabled = AxisEnabled.True;                  // 使X轴可用
        AREA.AxisX.IntervalAutoMode = IntervalAutoMode.VariableCount;   // X 轴标签数量,由显示的数据点数量自动调整
        AREA.AxisY.Enabled = AxisEnabled.True;
        AREA.AxisY.MajorTickMark.Enabled = false;
        AREA.CursorX.IsUserSelectionEnabled = true;             // 鼠标选择区域放大

        // series设置
        SERIES.ChartArea = "Line";
        SERIES.ChartType = SeriesChartType.Line;                // 折线图
        SERIES.Name = "随机数";
        SERIES.ToolTip = "数值:\n#VALY";                      // 鼠标悬浮在点上面显示提示(不够灵敏)

        // legend设置
        LEGEND.Alignment = System.Drawing.StringAlignment.Near;         // legend靠近显示,不然太占用地方了
        LEGEND.Docking = Docking.Left;                                  // 靠左显示
        LEGEND.DockedToChartArea = "Line";                              // 默认图例是显示在图的外面,占用地方
        LEGEND.IsDockedInsideChartArea = true;                          // 将图例放在图里面
        LEGEND.BackColor = System.Drawing.Color.Transparent;            // 无背景色,不然会挡住折线

        // 添加area series legend
        ChartPlot.ChartAreas.Add(AREA);
        ChartPlot.Series.Add(SERIES);
        ChartPlot.Legends.Add(LEGEND);

        // timer设置
        timer.Enabled = false;
        timer.Interval = INTERVAL;
        timer.Elapsed += Timer_Elapsed;
    }
    /// <summary>
    /// 定时更新图
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        Application.Current.Dispatcher.Invoke(() =>
        {
            if (SERIES.Points.Count >= MAXPLOT)
            {
                for(int i = 0; i < SERIES.Points.Count - MAXPLOT - 1; i++)
                {
                    SERIES.Points.RemoveAt(0);
                }
            }
            SERIES.Points.AddXY(DateTime.Now.ToString("HH:mm:ss"), GetRandomNumber());
            // 刷新图
            AREA.RecalculateAxesScale();
        });
    }
    /// <summary>
    /// 开始、暂停 画图
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btn_start_Click(object sender, RoutedEventArgs e)
    {
        if (timer.Enabled)
        {
            timer.Enabled = false;
            btn_start.Content = "开始";
        }
        else
        {
            timer.Enabled = true;
            btn_start.Content = "暂停";
        }
    }
    /// <summary>
    /// 改变间隔时间
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void rbtn_highspeed_Click(object sender, RoutedEventArgs e)
    {
        timer.Interval = 100;
    }
    private void rbtn_lowspeed_Click(object sender, RoutedEventArgs e)
    {
        timer.Interval = 500;
    }
    /// <summary>
    /// 改变图中最多点数
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void rbtn_manypoint_Click(object sender, RoutedEventArgs e)
    {
        MAXPLOT = 50;
    }
    private void rbtn_littlepoint_Click(object sender, RoutedEventArgs e)
    {
        MAXPLOT = 20;            
    }
    /// <summary>
    /// 产生随机数
    /// </summary>
    /// <returns></returns>
    private int GetRandomNumber()
    {
        byte[] buffer = Guid.NewGuid().ToByteArray(); 
        int iSeed = BitConverter.ToInt32(buffer, 0); 
        Random random = new Random(iSeed);
        return random.Next(-100, 100);
    }
}

3、最后

动态效果图来啦!!!!!!!!!

在WPF中使用Winform中自带的画图控件Chart,模拟动态更新数据

写在最后:最近做wpf一个项目,需要画图。可惜wpf没有自带的画图控件,而查询了很多了第三方控件(OxyPlot、Visifire、Dynamic Data Display)并尝试用了一下,唔,好难啊,主要是资料好少,还是winform的chart用的舒服。在此做个记录,以后用到的话也方便。

有问题欢迎交流。