我正在绘制一个WPFToolkit LineSeries图,除了ToolTip之外它一切正常。我想要一个工具提示来显示该行上任何点的鼠标的x和y值。我发现这适用于DataPoints(在我的情况下相当稀疏):http://istacee.wordpress.com/2013/03/19/wpf-toolkit-chart-custom-tooltip-on-lineseries-charts/,这适用于图表区域的任何一点:Show series value over any point on chart using tooltip c#。
到目前为止,这是我的代码:
<Grid.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="CommonLineSeriesDataPointTemplate" TargetType="chartingToolkit:LineDataPoint">
<Grid x:Name="Root" Opacity="1" />
</ControlTemplate>
<Style x:Key="CommonLineSeriesDataPoint" TargetType="chartingToolkit:LineDataPoint">
<Setter Property="Template" Value="{StaticResource CommonLineSeriesDataPointTemplate}" />
</Style>
<Style x:Key="lineSeriesStyle" TargetType="{x:Type chartingToolkit:LineSeries}">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="DataPointStyle" Value="{StaticResource CommonLineSeriesDataPoint}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chartingToolkit:LineSeries">
<Canvas x:Name="PlotArea">
<Polyline Points="{TemplateBinding Points}" >
<Polyline.Stroke>
<SolidColorBrush Color="Red"/>
</Polyline.Stroke>
</Polyline>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="chartTemplate" DataType="{x:Type Views:GraphCurve}">
<chartingToolkit:LineSeries ItemsSource="{Binding}"
IndependentValuePath="X"
DependentValuePath="Y"
Style="{StaticResource lineSeriesStyle}" />
</DataTemplate>
</ResourceDictionary>
</Grid.Resources>
<chartingToolkit:Chart BorderBrush="DarkGray"
SeriesSource="{Binding GraphItems}"
SeriesTemplate="{StaticResource chartTemplate}">
<chartingToolkit:Chart.Axes>
<chartingToolkit:LinearAxis Orientation="X" />
<chartingToolkit:LinearAxis Orientation="Y" />
</chartingToolkit:Chart.Axes>
</chartingToolkit:Chart>
有什么想法吗?
答案 0 :(得分:1)
您可以尝试使用MouseMove
事件,并跟踪鼠标的位置以显示在折线的工具提示中。 IRangeAxis
提供了一种方法GetValueAtPosition
,它采用像素坐标并将其转换为轴坐标中的值。
首先,将工具提示添加到折线:
<Polyline Points="{TemplateBinding Points}" >
<Polyline.Stroke>
<SolidColorBrush Color="Red"/>
</Polyline.Stroke>
<Polyline.ToolTip>
<ToolTip>
<StackPanel>
<TextBlock Text="{Binding HoverPoint.X}"/>
<TextBlock Text="{Binding HoverPoint.Y}"/>
</StackPanel>
</ToolTip>
</Polyline.ToolTip>
</Polyline>
这里我绑定了一个名为HoverPoint
的视图的视图模型的属性。确保在视图模型中定义它(我使用的是ReactiveUI,但您可以使用其他实现INotifyPropertyChanged
的内容):
private Point hoverPoint;
public Point HoverPoint
{
get { return hoverPoint; }
set { this.RaiseAndSetIfChanged(me => me.HoverPoint, ref hoverPoint, value); }
}
然后,最后,当鼠标在图表区域移动时,我们需要更新此属性。然后绑定将负责更新工具提示。如果您在图表上为MouseMove
事件添加处理程序:
<chartingToolkit:Chart MouseMove="Chart_MouseMove" ...
然后像这样填写处理程序:
private void Chart_MouseMove(object sender, MouseEventArgs e)
{
var chart = (Chart)sender;
var xAxisRange = (IRangeAxis)xAxis;
var yAxisRange = (IRangeAxis)yAxis;
var plotArea = FindDescendantWithName(chart, "PlotArea");
if (plotArea == null)
{
return;
}
var mousePositionInPixels = e.GetPosition(plotArea);
var mouseXPositionInChartUnits = (double)xAxisRange.GetValueAtPosition(new UnitValue(mousePositionInPixels.X, Unit.Pixels));
var mouseYPositionInChartUnits = (double)yAxisRange.GetValueAtPosition(new UnitValue(plotArea.Height - mousePositionInPixels.Y, Unit.Pixels));
((MainWindowViewModel)DataContext).HoverPoint = new Point(mouseXPositionInChartUnits, mouseYPositionInChartUnits);
}
public static FrameworkElement FindDescendantWithName(DependencyObject root, string name)
{
var numChildren = VisualTreeHelper.GetChildrenCount(root);
for (var i = 0; i < numChildren; i++)
{
var child = (FrameworkElement) VisualTreeHelper.GetChild(root, i);
if (child.Name == name)
{
return child;
}
var descendantOfChild = FindDescendantWithName(child, name);
if (descendantOfChild != null)
{
return descendantOfChild;
}
}
return null;
}
首先,我们获得对图表和轴的引用(我在XAML中命名了我的轴xAxis
和yAxis
)。
然后,我们需要找到图表模板的PlotArea
部分,这是绘制图表的位置(不包括轴等)。可能有更好的方法来实现此目的,但我使用过一个名为FindDescendantWithName
的简单方法来实现它。
然后,我使用GetPosition
来获取相对于此图表绘图区域的鼠标位置。最后,轴上的GetValueAtPosition
方法为我们提供了当前鼠标位置的图表坐标中的值,我们将这些协调设置在HoverPoint
属性中。
唯一的问题是图形线具有有限的厚度,因此您实际上可以移动鼠标并查看相同X值的不同Y值,反之亦然。但是,要扩展它以找到最近的绘图点并不难。然后,您可以将工具提示捕捉到最近的点。或者,如果你找到两个最近的点(一个在左边,一个在鼠标右边),你可以自己进行插值,找出Y对应的当前X值。我想这取决于你有多少如果值得做的话,要关心线的粗细。