QA@IT
«質問へ戻る

PolylineのPointsにPointが追加されている様子のスクリーンショットを追加しました。

104
本文
 
 逆に`#if true`のままですと「方法B」になり上手く動きません。私としては青い折れ線がどんどんランダムに伸びていくように書いたつもりですが、実際にはPolylineのPointsにはPointが追加され続けますがウィンドウ内のPolylineの描画が変化しません。念の為、アプリ実行中にブレークしてPolylineのPointsを覗きましたが、たしかに追加したPointが入っていました。
 
+![](http://cdn-ak.f.st-hatena.com/images/fotolife/i/iwadon/20140310/20140310184927_original.png?1394444978)
+
 StackOverflowに同様の質問があり、そちらの回答を読む限りは問題なく動く(単にバインドすれば動く)ように思うのですが、手元で試すと何が違うのかわかりませんがそのようには動きませんでした。
 
 http://stackoverflow.com/questions/5696820/binding-of-a-polyline-what-am-i-doing-wrong

PolylineクラスのPointsプロパティをViewModelのプロパティへバインドしたがうまく動かない

Livetを利用したWPF 4.5アプリケーションを書いています。

ウィンドウにあるPolylineのPointsへ動的にPointをaddしたいです。

そこで、Polyline自体をViewModelから参照できるようにして、そのPolylineのPointsへPointをaddするとうまく動きました(この方法を「方法A」とします)。

しかし、PolylineのPointsをViewModelのプロパティ(PointCollection)へバインドして、そのViewModelのプロパティに対してPointをaddしたものの、こちらは上手く動きませんでした(この方法を「方法B」とします)。

動作サンプルとして、起動するとウィンドウにランダムに折れ線を描画するアプリを書きました。PolyLineのPointsへランダムな座標のPointを0.2秒毎に追加していきます。

MainWindow.xaml:

<Window x:Class="LivetWPFApplication5.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"
        xmlns:v="clr-namespace:LivetWPFApplication5.Views"
        xmlns:vm="clr-namespace:LivetWPFApplication5.ViewModels"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="ContentRendered">
            <l:LivetCallMethodAction MethodTarget="{Binding}" MethodName="Initialize"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="Closed">
            <l:DataContextDisposeAction/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <Polyline x:Name="BluePolyLine" Stroke="Blue" Points="{Binding Path=BluePolyLinePoints}"/>
        <Polyline x:Name="RedPolyLine" Stroke="Red"/>
    </Grid>
</Window>

MainWindow.xaml.cs:

using System.Windows;

using LivetWPFApplication5.ViewModels;

namespace LivetWPFApplication5.Views
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var vm = (MainWindowViewModel)DataContext;
            vm.RedPolyline = RedPolyLine;
        }
    }
}

MainWindowViewModel.cs:

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

using Livet;

namespace LivetWPFApplication5.ViewModels
{
    public class MainWindowViewModel : ViewModel
    {
        private Polyline redPolyLine;
        private PointCollection bluePolyLinePoints = new PointCollection();
        private DispatcherTimer timer = new DispatcherTimer();
        private Random rnd = new Random();

        public void Initialize()
        {
            timer.Interval = new TimeSpan(0, 0, 0, 0, 200);
            timer.Tick += (sender, e) =>
            {
                var x = rnd.NextDouble() * 525;
                var y = rnd.NextDouble() * 350;
                var point = new Point(x, y);
#if true
                // (方法B) こちらでうまく動いて欲しい。
                BluePolyLinePoints.Add(point);
                RaisePropertyChanged("BluePolyLinePoints");
#else
                // (方法A) こちらはうまく動く。
                RedPolyline.Points.Add(point);
#endif
            };
            timer.Start();
        }

        public Polyline RedPolyline
        {
            get { return redPolyLine; }
            set
            {
                if (redPolyLine != value)
                {
                    redPolyLine = value;
                    RaisePropertyChanged();
                }
            }
        }

        public PointCollection BluePolyLinePoints
        {
            get { return bluePolyLinePoints; }
            set
            {
                if (bluePolyLinePoints != value)
                {
                    bluePolyLinePoints = value;
                    RaisePropertyChanged();
                }
            }
        }
    }
}

MainWindowViewModelのInitializeメソッドにある#if true#if falseにすると「方法A」でうまく動作します。

逆に#if trueのままですと「方法B」になり上手く動きません。私としては青い折れ線がどんどんランダムに伸びていくように書いたつもりですが、実際にはPolylineのPointsにはPointが追加され続けますがウィンドウ内のPolylineの描画が変化しません。念の為、アプリ実行中にブレークしてPolylineのPointsを覗きましたが、たしかに追加したPointが入っていました。

StackOverflowに同様の質問があり、そちらの回答を読む限りは問題なく動く(単にバインドすれば動く)ように思うのですが、手元で試すと何が違うのかわかりませんがそのようには動きませんでした。

http://stackoverflow.com/questions/5696820/binding-of-a-polyline-what-am-i-doing-wrong

以上、上手く説明できたかわかりませんが、マズい点などをご指摘いただければ幸いです。よろしくお願いいたします。

Livetを利用したWPF 4.5アプリケーションを書いています。

ウィンドウにあるPolylineのPointsへ動的にPointをaddしたいです。

そこで、Polyline自体をViewModelから参照できるようにして、そのPolylineのPointsへPointをaddするとうまく動きました(この方法を「方法A」とします)。

しかし、PolylineのPointsをViewModelのプロパティ(PointCollection)へバインドして、そのViewModelのプロパティに対してPointをaddしたものの、こちらは上手く動きませんでした(この方法を「方法B」とします)。

動作サンプルとして、起動するとウィンドウにランダムに折れ線を描画するアプリを書きました。PolyLineのPointsへランダムな座標のPointを0.2秒毎に追加していきます。

MainWindow.xaml:
```xml
<Window x:Class="LivetWPFApplication5.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"
        xmlns:v="clr-namespace:LivetWPFApplication5.Views"
        xmlns:vm="clr-namespace:LivetWPFApplication5.ViewModels"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="ContentRendered">
            <l:LivetCallMethodAction MethodTarget="{Binding}" MethodName="Initialize"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="Closed">
            <l:DataContextDisposeAction/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <Polyline x:Name="BluePolyLine" Stroke="Blue" Points="{Binding Path=BluePolyLinePoints}"/>
        <Polyline x:Name="RedPolyLine" Stroke="Red"/>
    </Grid>
</Window>
```

MainWindow.xaml.cs:
```csharp
using System.Windows;

using LivetWPFApplication5.ViewModels;

namespace LivetWPFApplication5.Views
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var vm = (MainWindowViewModel)DataContext;
            vm.RedPolyline = RedPolyLine;
        }
    }
}
```

MainWindowViewModel.cs:
```csharp
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

using Livet;

namespace LivetWPFApplication5.ViewModels
{
    public class MainWindowViewModel : ViewModel
    {
        private Polyline redPolyLine;
        private PointCollection bluePolyLinePoints = new PointCollection();
        private DispatcherTimer timer = new DispatcherTimer();
        private Random rnd = new Random();

        public void Initialize()
        {
            timer.Interval = new TimeSpan(0, 0, 0, 0, 200);
            timer.Tick += (sender, e) =>
            {
                var x = rnd.NextDouble() * 525;
                var y = rnd.NextDouble() * 350;
                var point = new Point(x, y);
#if true
                // (方法B) こちらでうまく動いて欲しい。
                BluePolyLinePoints.Add(point);
                RaisePropertyChanged("BluePolyLinePoints");
#else
                // (方法A) こちらはうまく動く。
                RedPolyline.Points.Add(point);
#endif
            };
            timer.Start();
        }

        public Polyline RedPolyline
        {
            get { return redPolyLine; }
            set
            {
                if (redPolyLine != value)
                {
                    redPolyLine = value;
                    RaisePropertyChanged();
                }
            }
        }

        public PointCollection BluePolyLinePoints
        {
            get { return bluePolyLinePoints; }
            set
            {
                if (bluePolyLinePoints != value)
                {
                    bluePolyLinePoints = value;
                    RaisePropertyChanged();
                }
            }
        }
    }
}
```

MainWindowViewModelのInitializeメソッドにある`#if true`を`#if false`にすると「方法A」でうまく動作します。

![](http://cdn-ak.f.st-hatena.com/images/fotolife/i/iwadon/20140310/20140310181457_original.png)

逆に`#if true`のままですと「方法B」になり上手く動きません。私としては青い折れ線がどんどんランダムに伸びていくように書いたつもりですが、実際にはPolylineのPointsにはPointが追加され続けますがウィンドウ内のPolylineの描画が変化しません。念の為、アプリ実行中にブレークしてPolylineのPointsを覗きましたが、たしかに追加したPointが入っていました。

![](http://cdn-ak.f.st-hatena.com/images/fotolife/i/iwadon/20140310/20140310184927_original.png?1394444978)

StackOverflowに同様の質問があり、そちらの回答を読む限りは問題なく動く(単にバインドすれば動く)ように思うのですが、手元で試すと何が違うのかわかりませんがそのようには動きませんでした。

http://stackoverflow.com/questions/5696820/binding-of-a-polyline-what-am-i-doing-wrong

以上、上手く説明できたかわかりませんが、マズい点などをご指摘いただければ幸いです。よろしくお願いいたします。

質問を投稿

PolylineクラスのPointsプロパティをViewModelのプロパティへバインドしたがうまく動かない

Livetを利用したWPF 4.5アプリケーションを書いています。

ウィンドウにあるPolylineのPointsへ動的にPointをaddしたいです。

そこで、Polyline自体をViewModelから参照できるようにして、そのPolylineのPointsへPointをaddするとうまく動きました(この方法を「方法A」とします)。

しかし、PolylineのPointsをViewModelのプロパティ(PointCollection)へバインドして、そのViewModelのプロパティに対してPointをaddしたものの、こちらは上手く動きませんでした(この方法を「方法B」とします)。

動作サンプルとして、起動するとウィンドウにランダムに折れ線を描画するアプリを書きました。PolyLineのPointsへランダムな座標のPointを0.2秒毎に追加していきます。

MainWindow.xaml:

<Window x:Class="LivetWPFApplication5.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"
        xmlns:v="clr-namespace:LivetWPFApplication5.Views"
        xmlns:vm="clr-namespace:LivetWPFApplication5.ViewModels"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="ContentRendered">
            <l:LivetCallMethodAction MethodTarget="{Binding}" MethodName="Initialize"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="Closed">
            <l:DataContextDisposeAction/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <Polyline x:Name="BluePolyLine" Stroke="Blue" Points="{Binding Path=BluePolyLinePoints}"/>
        <Polyline x:Name="RedPolyLine" Stroke="Red"/>
    </Grid>
</Window>

MainWindow.xaml.cs:

using System.Windows;

using LivetWPFApplication5.ViewModels;

namespace LivetWPFApplication5.Views
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var vm = (MainWindowViewModel)DataContext;
            vm.RedPolyline = RedPolyLine;
        }
    }
}

MainWindowViewModel.cs:

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

using Livet;

namespace LivetWPFApplication5.ViewModels
{
    public class MainWindowViewModel : ViewModel
    {
        private Polyline redPolyLine;
        private PointCollection bluePolyLinePoints = new PointCollection();
        private DispatcherTimer timer = new DispatcherTimer();
        private Random rnd = new Random();

        public void Initialize()
        {
            timer.Interval = new TimeSpan(0, 0, 0, 0, 200);
            timer.Tick += (sender, e) =>
            {
                var x = rnd.NextDouble() * 525;
                var y = rnd.NextDouble() * 350;
                var point = new Point(x, y);
#if true
                // (方法B) こちらでうまく動いて欲しい。
                BluePolyLinePoints.Add(point);
                RaisePropertyChanged("BluePolyLinePoints");
#else
                // (方法A) こちらはうまく動く。
                RedPolyline.Points.Add(point);
#endif
            };
            timer.Start();
        }

        public Polyline RedPolyline
        {
            get { return redPolyLine; }
            set
            {
                if (redPolyLine != value)
                {
                    redPolyLine = value;
                    RaisePropertyChanged();
                }
            }
        }

        public PointCollection BluePolyLinePoints
        {
            get { return bluePolyLinePoints; }
            set
            {
                if (bluePolyLinePoints != value)
                {
                    bluePolyLinePoints = value;
                    RaisePropertyChanged();
                }
            }
        }
    }
}

MainWindowViewModelのInitializeメソッドにある#if true#if falseにすると「方法A」でうまく動作します。

逆に#if trueのままですと「方法B」になり上手く動きません。私としては青い折れ線がどんどんランダムに伸びていくように書いたつもりですが、実際にはPolylineのPointsにはPointが追加され続けますがウィンドウ内のPolylineの描画が変化しません。念の為、アプリ実行中にブレークしてPolylineのPointsを覗きましたが、たしかに追加したPointが入っていました。

StackOverflowに同様の質問があり、そちらの回答を読む限りは問題なく動く(単にバインドすれば動く)ように思うのですが、手元で試すと何が違うのかわかりませんがそのようには動きませんでした。

http://stackoverflow.com/questions/5696820/binding-of-a-polyline-what-am-i-doing-wrong

以上、上手く説明できたかわかりませんが、マズい点などをご指摘いただければ幸いです。よろしくお願いいたします。

Livetを利用したWPF 4.5アプリケーションを書いています。

ウィンドウにあるPolylineのPointsへ動的にPointをaddしたいです。

そこで、Polyline自体をViewModelから参照できるようにして、そのPolylineのPointsへPointをaddするとうまく動きました(この方法を「方法A」とします)。

しかし、PolylineのPointsをViewModelのプロパティ(PointCollection)へバインドして、そのViewModelのプロパティに対してPointをaddしたものの、こちらは上手く動きませんでした(この方法を「方法B」とします)。

動作サンプルとして、起動するとウィンドウにランダムに折れ線を描画するアプリを書きました。PolyLineのPointsへランダムな座標のPointを0.2秒毎に追加していきます。

MainWindow.xaml:
```xml
<Window x:Class="LivetWPFApplication5.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"
        xmlns:v="clr-namespace:LivetWPFApplication5.Views"
        xmlns:vm="clr-namespace:LivetWPFApplication5.ViewModels"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="ContentRendered">
            <l:LivetCallMethodAction MethodTarget="{Binding}" MethodName="Initialize"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="Closed">
            <l:DataContextDisposeAction/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <Polyline x:Name="BluePolyLine" Stroke="Blue" Points="{Binding Path=BluePolyLinePoints}"/>
        <Polyline x:Name="RedPolyLine" Stroke="Red"/>
    </Grid>
</Window>
```

MainWindow.xaml.cs:
```csharp
using System.Windows;

using LivetWPFApplication5.ViewModels;

namespace LivetWPFApplication5.Views
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var vm = (MainWindowViewModel)DataContext;
            vm.RedPolyline = RedPolyLine;
        }
    }
}
```

MainWindowViewModel.cs:
```csharp
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

using Livet;

namespace LivetWPFApplication5.ViewModels
{
    public class MainWindowViewModel : ViewModel
    {
        private Polyline redPolyLine;
        private PointCollection bluePolyLinePoints = new PointCollection();
        private DispatcherTimer timer = new DispatcherTimer();
        private Random rnd = new Random();

        public void Initialize()
        {
            timer.Interval = new TimeSpan(0, 0, 0, 0, 200);
            timer.Tick += (sender, e) =>
            {
                var x = rnd.NextDouble() * 525;
                var y = rnd.NextDouble() * 350;
                var point = new Point(x, y);
#if true
                // (方法B) こちらでうまく動いて欲しい。
                BluePolyLinePoints.Add(point);
                RaisePropertyChanged("BluePolyLinePoints");
#else
                // (方法A) こちらはうまく動く。
                RedPolyline.Points.Add(point);
#endif
            };
            timer.Start();
        }

        public Polyline RedPolyline
        {
            get { return redPolyLine; }
            set
            {
                if (redPolyLine != value)
                {
                    redPolyLine = value;
                    RaisePropertyChanged();
                }
            }
        }

        public PointCollection BluePolyLinePoints
        {
            get { return bluePolyLinePoints; }
            set
            {
                if (bluePolyLinePoints != value)
                {
                    bluePolyLinePoints = value;
                    RaisePropertyChanged();
                }
            }
        }
    }
}
```

MainWindowViewModelのInitializeメソッドにある`#if true`を`#if false`にすると「方法A」でうまく動作します。

![](http://cdn-ak.f.st-hatena.com/images/fotolife/i/iwadon/20140310/20140310181457_original.png)

逆に`#if true`のままですと「方法B」になり上手く動きません。私としては青い折れ線がどんどんランダムに伸びていくように書いたつもりですが、実際にはPolylineのPointsにはPointが追加され続けますがウィンドウ内のPolylineの描画が変化しません。念の為、アプリ実行中にブレークしてPolylineのPointsを覗きましたが、たしかに追加したPointが入っていました。

StackOverflowに同様の質問があり、そちらの回答を読む限りは問題なく動く(単にバインドすれば動く)ように思うのですが、手元で試すと何が違うのかわかりませんがそのようには動きませんでした。

http://stackoverflow.com/questions/5696820/binding-of-a-polyline-what-am-i-doing-wrong

以上、上手く説明できたかわかりませんが、マズい点などをご指摘いただければ幸いです。よろしくお願いいたします。