OxyPlot WPF无法使用Button Click

时间:2016-11-01 17:00:22

标签: wpf buttonclick oxyplot

我在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

1 个答案:

答案 0 :(得分:3)

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很小,但随着程序的增长,这种结构化方式得到了回报。