DataBinding と PointCollection を使用した継続的な更新のためのポリライン
-
08-10-2019 - |
質問
まず最初に、達成したい目標を説明します。連続データ ストリームを視覚化したいと考えています (1 秒あたり最大 1000 個の値ですが、減らすことは可能です)。このデータ ストリームはグラフとして視覚化する必要があります。より正確には、とりわけ ECG の視覚化です。私の最初のアイデアは、ポリラインを使用し、それをポイント コレクションにバインドすることでした。ここでの問題は、UI に何も表示されないことです。おそらく、それはこのタスクに対する間違ったアプローチです。より良いアイデアは歓迎されます。これまでの私のコードは次のとおりです。まずビュー:
<Canvas>
<Polyline Points="{Binding Points}" Stroke="Red" StrokeThickness="2" />
</Canvas>
簡略化するために、MVVM パターンを使用する場合でもコードビハインドを使用します。これが、ポリラインの名前だけでなくバインディングを使用して値を追加したい理由でもあります。
public partial class MainWindow : Window
{
private short[] data = new short[]{ 10,30,50,70,90,110,130,150,170,190,210 };
private short[] data1 = new short[] { 15,14,16,13,17,12,18,11,19,10,24 };
public MainWindow()
{
InitializeComponent();
for (int i = 0; i < data.Length; i++)
{
Points.Add(new Point(data[i], data1[i]));
}
}
private PointCollection _points = new PointCollection();
public PointCollection Points
{
get { return _points; }
}
}
それが良いコーディング スタイルではないことはわかっていますが、最初のテストにはこれで十分です。x 値には配列 data を使用し、y 値には data1 を使用します。誰かそのバインディングの何が問題なのか教えてくれませんか?新しい値が発生するたびにビューを継続的に更新するにはどうすればよいでしょうか?事前にご協力いただきありがとうございます。
更新された新しいバージョン]ビュー:
<Window.Resources>
<my:PointCollectionConverter x:Key="myPointsConverter"/>
</Window.Resources>
<Grid Name="grid">
<Polyline x:Name="ekglineI" Points="{Binding Points, Converter={StaticResource myPointsConverter}}" Stroke="Red" StrokeThickness="2" />
<Button Content="Button" Click="button1_Click" />
</Grid>
起動時とその後ボタンをクリックしたときにポリラインを描画するコードビハインド。
public partial class MainWindow : Window, INotifyPropertyChanged
{
private short[] data = new short[] { 10, 30, 50, 70, 90, 110, 130, 150, 170, 190, 210 };
private short[] data2 = new short[] { 230, 250, 270, 290, 300, 310, 330, 350, 370, 390, 410 };
private short[] data1 = new short[] { 15, 14, 16, 13, 17, 12, 18, 11, 19, 10, 24 };
public mainWindow(){initializeComponent();グリッド.DataContext = これ;for (int i = 0;i < データの長さ;i ++){points.add(new Point(data [i]、data1 [i]));}} public event propertyChangedEventHandler PropertyChanged;private ObservableCollection _points = new ObservableCollection();public ObservableCollection Points {get {return _points;}}
private void button1_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < data2.Length; i++)
{
Points.Add(new Point(data2[i], data1[i]));
}
PropertyChanged(this, new PropertyChangedEventArgs("Points"));
}
ここで私がやりたいのは、次の行を削除することです。 grid.DataContext = this;
MVVM を使用できるようにするには、それとも別の可能性がありますか?
解決
Kai 変更通知をバインディングに伝播するには、変更通知を実装するコレクションを使用する必要があります。 PointCollection
これはしません。独自のコレクションを作成することもできますが、使用することをお勧めします ObservableCollection<T>
.
さらに、ここにも同様のものがあります SOポスト これは、UI に変更を認識させるための他のいくつかのオプションにも触れています。
他のヒント
Polyline Points アトリビュートをビューモデルに正常にバインドするには (つまり、バインドされた PointCollection が変更されたときに更新されるようにするには)、PointCollection をコレクションとして変更することは避けてください (Clear、Add など)。Polyline は、カスタム コンバーターを使用してポイントの ObservableCollection にバインドしても役に立たないことに気づきません。
代わりに、PointCollection をプロパティとして考慮する必要があります。新しく作成した PointCollection を使用して設定し、NotifyPropertyChanged イベントを発生させます。
private PointCollection points = new PointCollection();
public PointCollection Points
{
get { return points; }
set
{
points = value;
NotifyPropertyChanged("Points");
}
}
public void SomeUpdateFunc()
{
PointCollection pc = new PointCollection();
// Do some adding: pc.Add(new Point(x, y)); etc
this.Points = pc; // set via the setter, so the notification will fire
}
これで、ポリラインが適切に更新されるはずです。頑張ってください。
削除できる方法が少なくとも 1 つあります grid.DataContext = this;
追加 RelativeSource へのバインド グリッド自体に。この場合、xaml ファイルは次のようになります。
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:WpfApplication2">
<Grid Name="grid" DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:MainWindow, AncestorLevel=1}}">
<Canvas>
<Polyline Points="{Binding Points}" Stroke="Red" StrokeThickness="2" />
</Canvas>
</Grid>
そして、背後のコードは次のようになります
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
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.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
namespace WpfApplication2
{
public partial class MainWindow : Window , INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
for (int i = 0; i < data.Length; i++)
{
Points.Add(new Point(data[i], data1[i]));
}
NotifyPropertyChanged("Points");
}
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public PointCollection Points { get { return _points; } }
public event PropertyChangedEventHandler PropertyChanged;
private PointCollection _points = new PointCollection();
private short[] data = new short[] { 10, 30, 50, 70, 90, 110, 130, 150, 170, 190, 210 };
private short[] data1 = new short[] { 15, 14, 16, 13, 17, 12, 18, 11, 19, 10, 24 };
}
}