You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OxyPlot 2014.1.546:如何让自定义跟踪器保持打开直至点击外部?

解决OxyPlot跟踪器点击后保持显示直到外部点击的问题

针对你用OxyPlot 2014.1.546 + C# WPF开发时遇到的跟踪器消失问题,这里有两个可行的实践方案:

方案1:手动控制跟踪器的显示/隐藏逻辑

默认OxyPlot的跟踪器会在鼠标左键释放时自动隐藏,我们可以通过覆盖鼠标事件来改变这个行为:

  1. 先给XAML里的PlotView绑定鼠标事件:
<oxy:PlotView x:Name="TargetPlot" MouseLeftButtonUp="TargetPlot_MouseLeftButtonUp" MouseDown="TargetPlot_MouseDown" />
  1. 后台代码中处理事件,手动管控跟踪器状态:
private bool _trackerIsActive = false;
private HitTestResult _lastHitResult;

private void TargetPlot_MouseDown(object sender, MouseButtonEventArgs e)
{
    var plotView = sender as PlotView;
    if (plotView == null) return;

    // 转换鼠标位置为OxyPlot的视图坐标,检测点击是否命中数据点
    var screenPoint = e.GetPosition(plotView);
    var viewportPoint = plotView.ActualModel.TransformScreenToViewport(screenPoint);
    var hitResult = plotView.ActualModel.HitTest(viewportPoint);

    if (hitResult != null && hitResult.DataPoint != null)
    {
        // 命中数据点,显示跟踪器并标记为激活状态
        _lastHitResult = hitResult;
        _trackerIsActive = true;
        plotView.ShowTracker(hitResult);
        e.Handled = true;
    }
    else if (_trackerIsActive)
    {
        // 点击跟踪器外部,关闭跟踪器
        plotView.HideTracker();
        _trackerIsActive = false;
    }
}

private void TargetPlot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    // 阻止默认的跟踪器隐藏行为
    if (_trackerIsActive)
    {
        e.Handled = true;
    }
}

方案2:给跟踪器添加全局覆盖层捕获外部点击

通过自定义跟踪器模板,添加一个覆盖整个图表区域的透明层,用来监听外部点击事件:

  1. 在XAML中定义带覆盖层的跟踪器模板:
<oxy:PlotView>
    <oxy:PlotView.TrackerTemplate>
        <ControlTemplate>
            <Grid>
                <!-- 透明覆盖层,捕获所有外部点击 -->
                <Grid Background="Transparent" MouseDown="TrackerOverlay_MouseDown"/>
                <!-- 你的自定义跟踪器内容,包含操作按钮 -->
                <Border Background="#FFFFFF" BorderBrush="#CCCCCC" BorderThickness="1" Padding="10" Margin="15">
                    <StackPanel>
                        <TextBlock Text="X: {Binding DataPoint.X}" Margin="0 0 0 5"/>
                        <TextBlock Text="Y: {Binding DataPoint.Y}" Margin="0 0 0 10"/>
                        <Button Content="执行操作" Click="ActionButton_Click" Width="120"/>
                    </StackPanel>
                </Border>
            </Grid>
        </ControlTemplate>
    </oxy:PlotView.TrackerTemplate>
</oxy:PlotView>
  1. 后台处理覆盖层的点击事件,关闭跟踪器:
private void TrackerOverlay_MouseDown(object sender, MouseButtonEventArgs e)
{
    // 向上查找PlotView父控件并关闭跟踪器
    var plotView = FindParent<PlotView>(sender as UIElement);
    plotView?.HideTracker();
}

// 辅助方法:递归查找父级控件
private T FindParent<T>(UIElement element) where T : UIElement
{
    var parent = VisualTreeHelper.GetParent(element) as UIElement;
    while (parent != null)
    {
        if (parent is T target)
        {
            return target;
        }
        parent = VisualTreeHelper.GetParent(parent) as UIElement;
    }
    return null;
}

针对OxyPlot 2014.1.546版本的注意点

  • 这个旧版本的HitTest参数可能需要微调,如果TransformScreenToViewport报错,可以直接传入screenPoint的X/Y值作为屏幕坐标测试。
  • 如果用MVVM模式,可以把_trackerIsActive封装为ViewModel的属性,通过绑定来控制跟踪器显示,减少后台代码与控件的直接耦合。

内容的提问来源于stack exchange,提问作者dlf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:53:22