OxyPlot 2014.1.546:如何让自定义跟踪器保持打开直至点击外部?
解决OxyPlot跟踪器点击后保持显示直到外部点击的问题
针对你用OxyPlot 2014.1.546 + C# WPF开发时遇到的跟踪器消失问题,这里有两个可行的实践方案:
方案1:手动控制跟踪器的显示/隐藏逻辑
默认OxyPlot的跟踪器会在鼠标左键释放时自动隐藏,我们可以通过覆盖鼠标事件来改变这个行为:
- 先给XAML里的
PlotView绑定鼠标事件:
<oxy:PlotView x:Name="TargetPlot" MouseLeftButtonUp="TargetPlot_MouseLeftButtonUp" MouseDown="TargetPlot_MouseDown" />
- 后台代码中处理事件,手动管控跟踪器状态:
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:给跟踪器添加全局覆盖层捕获外部点击
通过自定义跟踪器模板,添加一个覆盖整个图表区域的透明层,用来监听外部点击事件:
- 在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>
- 后台处理覆盖层的点击事件,关闭跟踪器:
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
相关产品推荐
相关产品推荐

