允许用户通过单击wpf图表在wpf图表上创建线条系列
我有一个WPF图表,当前显示一个面积系列。我需要允许用户能够单击图表并为直线系列添加新点。我遇到的问题是,我似乎找不到将点从鼠标按钮Ventargs转换为LineDataPoint的方法允许用户通过单击wpf图表在wpf图表上创建线条系列,wpf,charts,toolkit,Wpf,Charts,Toolkit,我有一个WPF图表,当前显示一个面积系列。我需要允许用户能够单击图表并为直线系列添加新点。我遇到的问题是,我似乎找不到将点从鼠标按钮Ventargs转换为LineDataPoint的方法 private void chtPowerFlowMap_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { Point p = e.GetPosition(chtPowerFlowMap);
private void chtPowerFlowMap_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(chtPowerFlowMap);
points.Add(p); //Issue here is this will return a point in screen coordinates and not in chart coordinates
ls.ItemsSource = points; //ls is an existing lineseries and points is a List<Point> object
chtPowerFlowMap.Series.Add(ls);
}
private void-chtPowerFlowMap\u预览鼠标左键向下(对象发送器,鼠标按钮ventargs e)
{
点p=e.GetPosition(chtPowerFlowMap);
points.Add(p);//这里的问题是,这将返回屏幕坐标中的点,而不是图表坐标中的点
ls.ItemsSource=points;//ls是现有的线系列,而points是列表对象
chtPowerFlowMap.Series.Add(ls);
}
提前感谢。这里有一个完整的解决方案。你可以点击图表上的任何地方,在那个地方会有一个新的点 MainWindows.xaml
<chart:Chart x:Name="chart" MouseLeftButtonDown="Chart_MouseLeftButtonDown">
<chart:LineSeries ItemsSource="{Binding}" x:Name="lineSeries"
DependentValuePath="Value"
IndependentValuePath="Date"/>
</chart:Chart>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
private ObservableCollection<Item> items;
public MainWindow()
{
InitializeComponent();
Random rd = new Random();
items = new ObservableCollection<Item>(
Enumerable.Range(0, 10)
.Select(i => new Item
{
Date = DateTime.Now.AddMonths(i - 10),
Value = rd.Next(10,50)
}));
this.DataContext = items;
}
public class Item
{
public DateTime Date { get; set; }
public double Value { get; set; }
}
private void Chart_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var p = Mouse.GetPosition(this.lineSeries);
//ranges in the real values
var left = items.Min(i => i.Date);
var right = items.Max(i => i.Date);
var top = items.Max(i => i.Value);
var bottom = items.Min(i => i.Value);
var hRange = right - left;
var vRange = top - bottom;
//ranges in the pixels
var width = this.lineSeries.ActualWidth;
var height = this.lineSeries.ActualHeight;
//from the pixels to the real value
var currentX = left + TimeSpan.FromTicks((long)(hRange.Ticks * p.X / width));
var currentY = top - vRange * p.Y / height;
this.items.Add(new Item { Date = currentX, Value = currentY });
}
}
公共部分类主窗口:窗口
{
私人可观测收集项目;
公共主窗口()
{
初始化组件();
随机rd=新随机();
items=新的ObservableCollection(
可枚举范围(0,10)
.选择(i=>新项目
{
Date=DateTime.Now.AddMonths(i-10),
值=rd.Next(10,50)
}));
this.DataContext=项目;
}
公共类项目
{
公共日期时间日期{get;set;}
公共双值{get;set;}
}
私有无效图表\u MouseLeftButtonDown(对象发送器,MouseButtonEventArgs e)
{
var p=Mouse.GetPosition(this.lineSeries);
//实际值的范围
var left=items.Min(i=>i.Date);
var right=items.Max(i=>i.Date);
var top=items.Max(i=>i.Value);
var bottom=items.Min(i=>i.Value);
var hRange=右-左;
var vRange=顶部-底部;
//像素范围
var width=this.lineSeries.ActualWidth;
变量高度=this.lineSeries.ActualHeight;
//从像素到实际值
var currentX=左+时间跨度(从刻度((长)(hRange.Ticks*p.X/宽度));
var currentY=顶部-vRange*p.Y/高度;
this.items.Add(新项{Date=currentX,Value=currentY});
}
}
这是一个完整的解决方案。你可以点击图表上的任何地方,在那个地方会有一个新的点
MainWindows.xaml
<chart:Chart x:Name="chart" MouseLeftButtonDown="Chart_MouseLeftButtonDown">
<chart:LineSeries ItemsSource="{Binding}" x:Name="lineSeries"
DependentValuePath="Value"
IndependentValuePath="Date"/>
</chart:Chart>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
private ObservableCollection<Item> items;
public MainWindow()
{
InitializeComponent();
Random rd = new Random();
items = new ObservableCollection<Item>(
Enumerable.Range(0, 10)
.Select(i => new Item
{
Date = DateTime.Now.AddMonths(i - 10),
Value = rd.Next(10,50)
}));
this.DataContext = items;
}
public class Item
{
public DateTime Date { get; set; }
public double Value { get; set; }
}
private void Chart_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var p = Mouse.GetPosition(this.lineSeries);
//ranges in the real values
var left = items.Min(i => i.Date);
var right = items.Max(i => i.Date);
var top = items.Max(i => i.Value);
var bottom = items.Min(i => i.Value);
var hRange = right - left;
var vRange = top - bottom;
//ranges in the pixels
var width = this.lineSeries.ActualWidth;
var height = this.lineSeries.ActualHeight;
//from the pixels to the real value
var currentX = left + TimeSpan.FromTicks((long)(hRange.Ticks * p.X / width));
var currentY = top - vRange * p.Y / height;
this.items.Add(new Item { Date = currentX, Value = currentY });
}
}
公共部分类主窗口:窗口
{
私人可观测收集项目;
公共主窗口()
{
初始化组件();
随机rd=新随机();
items=新的ObservableCollection(
可枚举范围(0,10)
.选择(i=>新项目
{
Date=DateTime.Now.AddMonths(i-10),
值=rd.Next(10,50)
}));
this.DataContext=项目;
}
公共类项目
{
公共日期时间日期{get;set;}
公共双值{get;set;}
}
私有无效图表\u MouseLeftButtonDown(对象发送器,MouseButtonEventArgs e)
{
var p=Mouse.GetPosition(this.lineSeries);
//实际值的范围
var left=items.Min(i=>i.Date);
var right=items.Max(i=>i.Date);
var top=items.Max(i=>i.Value);
var bottom=items.Min(i=>i.Value);
var hRange=右-左;
var vRange=顶部-底部;
//像素范围
var width=this.lineSeries.ActualWidth;
变量高度=this.lineSeries.ActualHeight;
//从像素到实际值
var currentX=左+时间跨度(从刻度((长)(hRange.Ticks*p.X/宽度));
var currentY=顶部-vRange*p.Y/高度;
this.items.Add(新项{Date=currentX,Value=currentY});
}
}
如果将日期用作X轴,则会变得更加复杂。它需要关于点的实际宽度、实际高度、数据x范围、数据y范围和坐标的信息。如果我有时间,我会尝试实现类似的东西。如果使用日期作为X轴,它会变得更加复杂。它需要关于点的实际宽度、实际高度、数据x范围、数据y范围和坐标的信息。如果我有时间,我会尝试实现类似的东西。酷…工作得很好。如果图表工具包能够基于一组轴将鼠标点转换为图表值,那就太好了。再次感谢。只是好奇,为什么你得到的是与系列相关的点而不是图表?@Chris因为wpf图表是系列和轴的组合,因此我从轴的真正开始,从坐标原点测量。为了公正起见,起初我试图使用整个图表,但在发射和测试之后,我改变了控制。另外,这个例子对系列之外的点击做出响应,可以通过比较左侧和底部的值与系列的边框来纠正。酷…工作得很好。如果图表工具包能够基于一组轴将鼠标点转换为图表值,那就太好了。再次感谢。只是好奇,为什么你得到的是与系列相关的点而不是图表?@Chris因为wpf图表是系列和轴的组合,因此我从轴的真正开始,从坐标原点测量。为了公正起见,起初我试图使用整个图表,但在发射和测试之后,我改变了控制。此示例还响应序列外部的单击,可以通过将左侧和底部值与序列的边框进行比较来更正。