LoginSignup
0
1

More than 3 years have passed since last update.

[C#/xaml] System.Windows.Pointのリストを使って線を引く

Last updated at Posted at 2020-06-26

もくじ
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

やりたいこと

System.Windows.Pointクラスと、System.Windows.Media.PointCollectionクラスを使って、xamlで作った画面に線を引きたい。
System.Drawing.PointクラスではなくSystem.Windows.Pointクラス。

流れ

  • 準備
    • System.Windows.Pointを持たせるクラスに(以下、Pointクラスと言う)
      InotifyPropertyChangedを実装する
    • PointPointCollectionに変換してくれるコンバータをつくる
  • 線を書く
    • System.Windows.PointのObservableCollectionをつくる
    • 好きなタイミングで、線を引きたい座標を入れたPointをObservableCollectionにAddする
    • OnPropertyChanged(PropertyChanged)を実行する
    • →PointのObservableCollectionにあった線が描画される

前提

.NET core 3.1で実験。

サンプル

画面

MainWindow.xaml
<Window x:Class="WpfApp57.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp57"
        xmlns:conv="clr-namespace:Converter"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        Name="root">
    <Window.Resources>
        <conv:ListPointToPointCollectionConverter x:Key="ListPointToPointCollectionConverter" />
    </Window.Resources>
    <Grid>
        <Canvas>
            <!-- 線 -->
            <Polyline Name="MyLine" Stroke="Red" StrokeThickness="1" 
                      Points="{Binding Points, ElementName=root, Converter={StaticResource ListPointToPointCollectionConverter}}"/>
            <!-- ボタン -->
            <Button Content="Button" Height="100" Canvas.Left="10" Canvas.Top="324" Width="100" Click="Button_Click"/>
        </Canvas>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
using System.Collections.ObjectModel;

namespace WpfApp57
{
    /// <summary>
    /// ボタンをおしたら、サインカーブを書く
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        // ------------------------------------------------

        public ObservableCollection<Point> Points
        {
            get { return _points; }
            set { _points = value; OnPropertyChanged(nameof(Points)); }
        }
        private ObservableCollection<Point> _points = new ObservableCollection<Point>();

        public MainWindow()
        {
            InitializeComponent();

            // Point追加時に自動でOnPropertyChangedしてくれるようにする
            Points.CollectionChanged += ((sender, e) =>
            {
                var oc = sender as ObservableCollection<Point>;
                OnPropertyChanged(nameof(Points));
                Debug.WriteLine("count = " + oc.Count);
            });
        }

        private double y = 150.0;

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var _ = Task.Run(() =>
            {
                this.Dispatcher.Invoke(new Action(async () =>
                {
                    for (int i = 0; i < 100; i++)
                    {
                        Points.Add(new Point((double)i, y + 150.0 * Math.Sin((double)i / (Math.PI))));
                        OnPropertyChanged(nameof(Points));
                        await Task.Delay(30);
                    }
                }));
            });
        }
    }
}

コンバータ

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Collections.ObjectModel;

namespace Converter
{
    public class ListPointToPointCollectionConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var points = (ObservableCollection<Point>)value;
            return points != null ? new PointCollection(points) : null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

実行イメージ

image.png

備考

試してないが、コンバータを使わなくても、コード内でPointをPointCollectionにしてもよいと思う。

コード

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1