Полилиния использует DataBinding и PointCollection для постоянного обновления - PullRequest
5 голосов
/ 18 октября 2010


прежде всего я опишу свою цель, которую хочу достичь.Я хочу визуализировать непрерывный поток данных (максимум 1000 значений в секунду, но его можно уменьшить).Этот поток данных должен быть визуализирован в виде диаграммы - если быть более точным, это, среди прочего, визуализация ЭКГ.Моей первой идеей было использование полилинии и связывание ее с коллекцией точек.Проблема в том, что на интерфейсе ничего не отображается.Возможно, это неправильный подход к этой задаче.Лучшие идеи приветствуются.Вот мой код до сих пор.Сначала представление:

 
<code><Canvas></code>
  <code><Polyline Points="{Binding Points}" Stroke="Red" StrokeThickness="2" /></code>
<code></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 };</p>

<pre><code>    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 и data1 для значений y.Может кто-нибудь сказать мне, что не так с этим связыванием?Что нужно сделать для постоянного обновления представления при появлении новых значений?
Заранее спасибо за помощь.

[Обновленная новая версия] Представление:


<code><Window.Resources></code>
        <code><my:PointCollectionConverter x:Key="myPointsConverter"/></code>
<code></Window.Resources></code>
    <code><Grid Name="grid"></code>
        <code><Polyline x:Name="ekglineI" Points="{Binding Points, Converter={StaticResource myPointsConverter}}" Stroke="Red" StrokeThickness="2"  /></code>
        <code><Button Content="Button" Click="button1_Click" /></code>
<code></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 };</p>

<p>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; }
        }</p>

<pre><code>    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 или есть другая возможность?

Ответы [ 3 ]

7 голосов
/ 12 октября 2012

Чтобы успешно связать атрибут Polyline Points с вашей моделью представления (т. Е. Чтобы он обновлялся при изменении привязанной PointCollection), вам следует избегать изменения PointCollection как коллекции (Clear, Add и т. Д.). Полилиния не заметит, что даже привязка к 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
    }

Теперь Полилиния должна быть обновлена ​​правильно, удачи!

2 голосов
/ 06 ноября 2012

Существует как минимум один возможный способ удалить grid.DataContext = this;

Добавить Binding to 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 };


    }
}
1 голос
/ 18 октября 2010

Кай, чтобы уведомление об изменениях распространялось на ваши привязки, вы должны использовать коллекцию, которая реализует уведомление об изменениях, PointCollection этого не делает. Вы можете создать свою собственную коллекцию, но я бы рекомендовал использовать ObservableCollection<T>.

Кроме того, здесь есть аналогичная SO запись , которая также затрагивает несколько других опций для информирования пользовательского интерфейса о ваших изменениях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...