如何在整个WPFToolkit LineSeries上获得工具提示?

时间:2013-06-18 15:03:12

标签: wpftoolkit

我正在绘制一个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>

有什么想法吗?

1 个答案:

答案 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中命名了我的轴xAxisyAxis)。

然后,我们需要找到图表模板的PlotArea部分,这是绘制图表的位置(不包括轴等)。可能有更好的方法来实现此目的,但我使用过一个名为FindDescendantWithName的简单方法来实现它。

然后,我使用GetPosition来获取相对于此图表绘图区域的鼠标位置。最后,轴上的GetValueAtPosition方法为我们提供了当前鼠标位置的图表坐标中的值,我们将这些协调设置在HoverPoint属性中。

唯一的问题是图形线具有有限的厚度,因此您实际上可以移动鼠标并查看相同X值的不同Y值,反之亦然。但是,要扩展它以找到最近的绘图点并不难。然后,您可以将工具提示捕捉到最近的点。或者,如果你找到两个最近的点(一个在左边,一个在鼠标右边),你可以自己进行插值,找出Y对应的当前X值。我想这取决于你有多少如果值得做的话,要关心线的粗细。