1 新建wpf应用
2 新建MainViewModel类
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApp5
{
public class MainViewModel:INotifyPropertyChanged
{
public ObservableCollection<Point> Points { get; set; } = new ObservableCollection<Point>();
private int _OffsetX = 0;
public int OffsetX
{
get { return _OffsetX; }
set { _OffsetX = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("OffsetX")); }
}
public MainViewModel()
{
Task.Run(async () =>
{
double angle = 0.0;
double x = 0.0;
while (angle < 360)
{
await Task.Delay(50);
double value = Math.Cos(Math.PI * (angle / 180));
angle += 30;
Application.Current.Dispatcher.Invoke(() =>
{
Points.Add(new Point(x, value * 40 + 50));
x += 20;
if (Points.Count > 50)
{
OffsetX -=20;
Points.RemoveAt(0);
}
});
if (angle >= 360)
{
angle = 0.0;
}
}
});
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
3 在MainWindow.xaml上添加PolyLine,因为其Points属性是PointCollection类型,该类型没有实现INotifyCollectionChanged, INotifyPropertyChanged这些接口,所以考虑添加附件属性来作为中转来绑定
<Window x:Class="WpfApp5.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:WpfApp5"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Polyline local:PointsHelper.Points="{Binding Points}" Stroke="Red" StrokeThickness="1" >
<Polyline.RenderTransform>
<TranslateTransform X="{Binding OffsetX}"/>
</Polyline.RenderTransform>
</Polyline>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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;
namespace WpfApp5
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
}
}
4 新建PointsHelper类,添加附件属性PointsProperty,在其PropertyChangedCallback关联的委托中为PolyLine的Points属性来赋值。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows;
using System.Windows.Shapes;
namespace WpfApp5
{
public class PointsHelper
{
public static ObservableCollection<Point> GetPoints(DependencyObject obj)
{
return (ObservableCollection<Point>)obj.GetValue(PointsProperty);
}
public static void SetPoints(DependencyObject obj, int value)
{
obj.SetValue(PointsProperty, value);
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PointsProperty =
DependencyProperty.RegisterAttached("Points", typeof(ObservableCollection<Point>), typeof(PointsHelper), new PropertyMetadata(null, new PropertyChangedCallback(OnPointsChanged)));
private static void OnPointsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = d as Polyline;
var ps = e.NewValue as ObservableCollection<Point>;
ps.CollectionChanged += (se, ev) =>
{
obj.Points = new System.Windows.Media.PointCollection(e.NewValue as ObservableCollection<Point>);
};
}
}
}