web-dev-qa-db-ja.com

データが変更されたときにoxyplotプロットを更新する方法

GUI for the program

オキシプロットグラフは、6つのユーザー入力テキストボックスから派生した13ポイントをグラフ化します。テキストボックスの値は、MainWindow.xaml.csクラスのパブリック変数に保持されます。ユーザーがテキストボックスにEnterキーを押すと、変数が更新されます。更新ボタンでグラフを更新するにはどうすればよいですか。

private void RefreshButton_Click(object sender, RoutedEventArgs e)
        {
            //Refresh The Graph
        }

私はこれを使用して行われると思います

PlotModel.RefreshPlot() 

メソッドですが、Oxyplotのドキュメントの質が低いため、どのように実装するのかわかりません。

21
Jkallus

NuGetを介してOxyPlotの新しいバージョンに更新しました。私はOxyPlot.Wpf v20014.1.277.1を使用していますが、RefreshPlot(使用できなくなりました)の代わりにPlotModelInvalidatePlot(bool updateData)を呼び出す必要があると思います。サンプルコードでこれをテストしたところ、期待どおりに機能しました。

プロットを更新する場合andデータコレクションを更新する場合、trueを呼び出しに渡す必要があります。

PlotModel.InvalidatePlot(true)
34
ruttopia

「ある種の」自動更新を取得するために見つけた最もクリーンな方法は、LineSeriesのItemsSourceであるコレクションのCollectionChangedに反応することです。

ViewModelの場合:

ObservableCollection<DataPoint> Data { get; set; } 
    = new ObservableCollection<DataPoint>();

public PlotModel PlotModel
{
    get { return _plot_model; }
    set
    {
        _plot_model = value;
        RaisePropertyChanged(() => PlotModel);
    }
}
PlotModel _plot_model;

// Inside constructor:
Data.CollectionChanged += (a, b) => PlotModel.InvalidatePlot(true);
6
heltonbiker

x:NameからXAMLのOxyPlotインスタンスへ:

<oxy:Plot x:Name="Plot1"/>

ボタンのクリックハンドラーで、次のように更新します。

private void RefreshButton_Click(object sender, RoutedEventArgs e)
{
   Plot1.RefreshPlot(true);
}
6
Rohit Vats

同じ問題で同じ質問をした後、唯一の有効な解決策は(少なくとも私の観点では)次のように見えるでしょう:

PlotView.InvalidatePlot(true)

1つまたは複数のSeriesを更新した後、PlotViewを更新してください。

リフレッシュレートは、セリエが更新される頻度または頻度によって異なります。

コードスニペットを次に示します(Xamarin Androidで動作しますが、とにかく動作するはずです):

PlotView resultsChart = FindViewById<PlotView>(Resource.Id.resultsChart);
PlotModel plotModel = new PlotModel
{
    // set here main properties such as the legend, the title, etc. example :
    Title = "My Awesome Real-Time Updated Chart",
    TitleHorizontalAlignment = TitleHorizontalAlignment.CenteredWithinPlotArea,
    LegendTitle = "I am a Legend",
    LegendOrientation = LegendOrientation.Horizontal,
    LegendPlacement = LegendPlacement.Inside,
    LegendPosition = LegendPosition.TopRight
    // there are many other properties you can set here
}

// now let's define X and Y axis for the plot model

LinearAxis xAxis = new LinearAxis();
xAxis.Position = AxisPosition.Bottom;
xAxis.Title = "Time (hours)";

LinearAxis yAxis = new LinearAxis();
yAxis.Position = AxisPosition.Left;
yAxis.Title = "Values";

plotModel.Axes.Add(xAxis);
plotModel.Axes.Add(yAxis);

// Finally let's define a LineSerie

LineSeries lineSerie = new LineSeries
 {
    StrokeThickness = 2,
    CanTrackerInterpolatePoints = false,
    Title =  "Value",
    Smooth = false
  };
plotModel.Series.Add(lineSerie);
resultsChart.Model = plotModel;

DataPointsLineSerieに追加し、それに応じてPlotViewを自動的に更新する必要がある場合は、次のようにします。

resultsChart.InvalidatePlot(true);

そうすると、PlotViewが自動的に更新されます。

補足的に、PlotViewは、タッチ、ズームのピンチ、またはUI関連のイベントなどのイベントが発生したときにも更新されます。

私が助けてくれることを願っています。私はこれに非常に長い間苦労しました。

4
Mackovich

プロットの更新方法( OxyPlot documentation )の3つの選択肢があります:

  • ModelコントロールのPlotViewプロパティを変更します
  • InvalidateコントロールでPlotViewを呼び出します
  • InvalidatePlotModelを呼び出します
3
honzakuzel1989

現在のOxyPlot.Wpf(1.0.0-unstable1983)には、2つのオプションがあります。

  1. 更新が必要な場合は、Series.ItemsSourceプロパティをXAMLからビューモデルのコレクションにバインドし、コレクション全体を交換します。これにより、より大きなデータセットでの非同期更新の同時実行も可能になります。
  2. タイプintPlot.InvalidateFlagプロパティをビューモデルにバインドし、更新が必要になるたびにインクリメントします。ただし、このアプローチはテストしていません。

次のコードは両方のオプションを示しています(1つを選択)。 XAML:

<oxy:Plot InvalidateFlag="{Binding InvalidateFlag}">
    <oxy:Plot.Series>
        <oxy:LineSeries ItemsSource="{Binding DataSeries}" />
      </oxy:Plot.Series>
 </oxy:Plot>

ViewModelの更新:

private async Task UpdateAsync()
{
    // TODO do some heavy computation here
    List<DataPoint> data = await ...

    // option 1: Trigger INotifyPropertyChanged on the ItemsSource.
    //           Concurrent access is ok here.
    this.DataSeries = data; // switch data sets

    // option 2: Update the data in place and trigger via flag
    //           Only one update at a time.
    this.DataSeries.Clear();
    data.ForEach(this.DataSeries.Add);
    this.InvalidateFlag++;
}
3
Patrick Stalph

さらに2年後...オキシプロットモデルがなく、上記の名前付き関数の一部が欠落しているため、この解決策が役立ちます。

コードビハインド:

public partial class LineChart : UserControl
{
    public LineChart()
    {
        InitializeComponent();

        DataContext = this;
        myChart.Title = "hier könnte Ihr Text stehen!";

        this.Points = new List<DataPoint>();
        randomPoints();
    }


    public IList<DataPoint> Points { get; private set; }

    public void randomPoints()
    {
        Random rd = new Random();
        String myText = "";

        int anz = rd.Next(30, 60);

        for (int i = 0; i < anz; i++)
            myText += i + "," + rd.Next(0, 99) + ";";

        myText = myText.Substring(0, myText.Length - 1);
        String[] splitText = myText.Split(';');

        for (int i = 0; i < splitText.Length; i++)
        {
            String[] tmp = splitText[i].Split(',');
            Points.Add(new DataPoint(Double.Parse(tmp[0].Trim()), Double.Parse(tmp[1].Trim())));
        }

        while (Points.Count > anz)
            Points.RemoveAt(0);

        myChart.InvalidatePlot(true);
    }
}

データを更新するには IList全体を交換せず、新しいDataPointを追加して、位置0の古いものを削除します。

XAML:

<UserControl x:Class="UxHMI.LineChart"
         xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.Microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:UxHMI"
         xmlns:oxy="http://oxyplot.org/wpf"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="Container" Background="White">
    <oxy:Plot x:Name="myChart" Title="{Binding Title}" FontFamily="Bosch Sans Medium" Foreground="#FF0C6596" FontSize="19" Canvas.Left="298" Canvas.Top="32" Background="AliceBlue" Margin="0,0,10,0">
        <oxy:Plot.Series>
            <oxy:LineSeries x:Name="ls" Background="White" ItemsSource="{Binding Points}" LineStyle="Solid" Color="ForestGreen" MarkerType="None" MarkerSize="5" MarkerFill="Black">

            </oxy:LineSeries>
        </oxy:Plot.Series>
    </oxy:Plot>
    <Button x:Name="button" Content="Random" HorizontalAlignment="Left" Margin="0,278,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>

重要なのはx:Name = "myChart"ItemsSource = "{Binding Points}"です

私はこれが誰かに役立つことを願っています

1
prototype0815