OxyPlot WPF 不适用于按钮单击

Posted

技术标签:

【中文标题】OxyPlot WPF 不适用于按钮单击【英文标题】:OxyPlot WPF not working with Button Click 【发布时间】:2017-03-14 21:00:45 【问题描述】:

我在使用 OxyPlot 时遇到了一些问题,我无法通过他们的文档或其他搜索来解决这些问题。我正在开发一个 wpf 应用程序,它允许用户使用按钮单击事件打开 .csv,然后执行一些数学运算并报告一些有用的信息。我想绘制一些生成的数据,因此是 OxyPlot。由于某种原因,当生成它的代码在按钮单击事件中时,我无法填充该图。为了说明这里是一个较小的例子: 此代码有效(xaml):

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:oxy="http://oxyplot.org/wpf"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication1"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="20,20,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
    <Grid HorizontalAlignment="Left" Height="255" Margin="20,47,0,0" VerticalAlignment="Top" Width="477">
        <oxy:PlotView Model="Binding ScatterModel"/>
    </Grid>
</Grid>

用这个:

public partial class MainWindow : Window

    public MainWindow()
    
       InitializeComponent();
        DataContext = this;
        var tmp = new PlotModel  Title = "Scatter plot", Subtitle = "y = x" ;
        var s2 = new LineSeries
        
            StrokeThickness = 1,
            MarkerSize = 1,
            MarkerStroke = OxyColors.ForestGreen,
            MarkerType = MarkerType.Plus
        ;

        for (int i = 0; i < 100; i++)
        
            s2.Points.Add(new DataPoint(i, i));
        
        tmp.Series.Add(s2);
        this.ScatterModel = tmp;
    

    private void button_Click(object sender, RoutedEventArgs e)
    

    
    public PlotModel ScatterModel  get; set; 

并产生这个: Plot Working

但是,在不更改 xaml 的情况下,如果我复制/粘贴按钮单击事件下方的代码:

public partial class MainWindow : Window

    public MainWindow()
    
       InitializeComponent();

    

    private void button_Click(object sender, RoutedEventArgs e)
    
        DataContext = this;
        var tmp = new PlotModel  Title = "Scatter plot", Subtitle = "y = x" ;
        var s2 = new LineSeries
        
            StrokeThickness = 1,
            MarkerSize = 1,
            MarkerStroke = OxyColors.ForestGreen,
            MarkerType = MarkerType.Plus
        ;

        for (int i = 0; i < 100; i++)
        
            s2.Points.Add(new DataPoint(i, i));
        
        tmp.Series.Add(s2);
        this.ScatterModel = tmp;
    
    public PlotModel ScatterModel  get; set; 

情节永远不会生成:Not working:

我试过移动 DataContext = this;备份到公共 MainWindow(),反之亦然,使用 InitializeComponent();不用找了。我也试过定义

<Window.DataContext>
    <local:MainWindow/>
</Window.DataContext>

在 xaml 中,但在构建期间会引发异常/无限循环错误。 一些简单的事情,我担心我不了解 OxyPlot 的实施?

谢谢! CSMDakota

【问题讨论】:

它与 OxyPlot 无关。您需要实现INotifyPropertyChanged,因此您的ScatterModel 将在按钮单击后更新。循环来自&lt;local:MainWindow/&gt; 行。在 MVVM 中,它将是 &lt;local:ViewModel/&gt; 【参考方案1】:

INotifyPropertyChanged 使您的视图与程序的状态保持同步。一种方法是实现ViewModel(MVVM 模式)。

所以让我们创建一个。 ViewModelBase介绍OnPropertyChanged(),更新ScatterModel的方法。

ViewModels.cs

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using OxyPlot;

namespace WpfApplication1

    public class ViewModel : ViewModelBase
    
        private PlotModel _scatterModel;
        public PlotModel ScatterModel
        
            get  return _scatterModel; 
            set
            
                if (value != _scatterModel)
                
                    _scatterModel = value;
                    OnPropertyChanged();
                
            
        
    

    public class ViewModelBase : INotifyPropertyChanged
    
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] String propName = null)
        
            // C#6.O
            // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propName));
        
    

您现在可以在 MainWindow.xaml 中添加

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>

MainWindow.xaml.cs

public partial class MainWindow : Window

    public MainWindow()
    
        InitializeComponent();
    

    private void button_Click(object sender, RoutedEventArgs e)
    
        var tmp = new PlotModel  Title = "Scatter plot", Subtitle = "y = x" ;
        var s2 = new LineSeries
        
            StrokeThickness = 1,
            MarkerSize = 1,
            MarkerStroke = OxyColors.ForestGreen,
            MarkerType = MarkerType.Plus
        ;

        for (int i = 0; i < 100; i++)
        
            s2.Points.Add(new DataPoint(i, i));
        
        tmp.Series.Add(s2);
        ViewModel.ScatterModel = tmp;
    

    // C#6.O
    // public ViewModel ViewModel => (ViewModel)DataContext;
    public ViewModel ViewModel
    
        get  return (ViewModel)DataContext; 
    

请注意,我们不再设置 DataContext = this,这被认为是不好的做法。在这种情况下,ViewModel 很小,但随着程序的发展,这种结构方式会得到回报。

【讨论】:

放克,太棒了!感谢您的详细回答,我按照您的指示进行操作,现在正在按预期工作。在我回到我的主程序之前,我会确保我理解你在这里做了什么,我仍然需要仔细研究它。谢谢!

以上是关于OxyPlot WPF 不适用于按钮单击的主要内容,如果未能解决你的问题,请参考以下文章

单击事件不适用于以编程方式/动态创建的选项按钮

本机 Javascript 单击事件不适用于按钮中的图标

OxyPlot 导出图片及 WPF 元素导出为图片的方法

OxyPlot.Wpf 图表控件使用备忘

OxyPlot 导出图片及 WPF 元素导出为图片的方法

我必须双击一个按钮才能使动画工作。它不适用于单击