使用 DataBinding 和 PointCollection 进行连续更新的折线
首先,我描述我想要实现的目标。我想要可视化连续的数据流(每秒最多 1000 个值,但可以减少)。该数据流应该可视化为图表 - 更准确地说,它是心电图等的可视化。 我的第一个想法是使用折线并将其绑定到点集合。这里的问题是 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; }
}
}
I know that is no good coding style but for first tests its enough for me. I use array data for x-values and data1 for y-values. Can anyone tell me whats wrong with that binding? What's to be done for a continuous update of the view, whenever new values occur?Thanks for your help in advance.
[更新新版本] 观点:
<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>
The code-behind which draws a polyline on startup and later on when a button is clicked.
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 };
公共主窗口()
{
初始化组件();
网格.DataContext = this;
for (int i = 0; i < data.Length; i++)
{
Points.Add(new Point(data[i], data1[i]));
}
}
公共事件 PropertyChangedEventHandler PropertyChanged;
私有 ObservableCollection _points = new ObservableCollection();
公共 ObservableCollection 点
{
获取{返回_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 或者还有其他可能性吗?
first of all I describe my objective I want to achive. I want to visualise a continuous data stream (maximum 1000 values per second but could be reduced). This data stream should be visualised as a chart - being more precise it's a visualisation of an ECG among other things.
My first idea was using polyline and bind it to a point collection. The problem here is that nothing is shown on the UI. Perhaps it's a wrong aproach for this task. Better ideas are welcomed. Here ist my code so far. First the View:
<Canvas>
<Polyline Points="{Binding Points}" Stroke="Red" StrokeThickness="2" />
</Canvas>
For the sake of simplicity I use the code-behind even though I use the MVVM-pattern. That's also the reason why I want to use the binding and not just the name of the polyline and add the values.
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; } }
}
I know that is no good coding style but for first tests its enough for me. I use array data for x-values and data1 for y-values. Can anyone tell me whats wrong with that binding? What's to be done for a continuous update of the view, whenever new values occur?
Thanks for your help in advance.[Updated new version]
The view:
<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>
The code-behind which draws a polyline on startup and later on when a button is clicked.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(); grid.DataContext = this; for (int i = 0; i < data.Length; 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")); }
Now what I want to do is getting rid of this line:
grid.DataContext = this;
so that I can use my MVVM or is there another possibility?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为了将 Polyline Points 属性成功绑定到您的视图模型(即在绑定的 PointCollection 更改时更新它),您应该避免将 PointCollection 更改为集合(清除、添加等)。 Polyline 不会注意到这一点,即使使用自定义转换器绑定到 ObservableCollection of Points 也无济于事。
相反,您应该将 PointCollection 视为一个属性:使用新创建的 PointCollection 设置它,并触发 NotifyPropertyChanged 事件:
现在折线应该正确更新,祝您好运!
In order to bind the Polyline Points attribute to your viewmodel successfully (i.e. to have it update when the bound PointCollection changes), you should avoid changing the PointCollection as a collection (Clear, Add, etc). The Polyline will not notice that, even binding to an ObservableCollection of Points with a custom converter will not help.
Instead, you should consider your PointCollection as a property: set it with a newly created PointCollection, and fire a NotifyPropertyChanged event:
Now the Polyline should be updated properly, good luck!
Kai 要将更改通知传播到您的绑定,您应该使用实现更改通知的集合,
PointCollection
不会执行此操作。您可以创建自己的集合,但我建议使用ObservableCollection
。另外这里有一个类似的 SO post 其中还涉及一些其他选项,使 UI 知道您的更改。
Kai to make the change notification propagate to your bindings you should be making use of a collection which implements change notificaiton,
PointCollection
does not do this. You could create your own collection however I'd recommend making use ofObservableCollection<T>
.In addition here is a similar SO post which also touches on a few other options for making the UI aware of your changes.
至少有一种可能的方法可以删除
grid.DataContext = this;
添加 绑定到relativesource到网格本身。在这种情况下,xaml 文件将如下所示
后面的代码会是这样的
There is at least one possible way to remove
grid.DataContext = this;
Add Binding to RelativeSource to the grid itself. In this case the xaml file will looks like
And the code behind will be like this