短:在调用myModel.InvalidatePlot(true / false)更新模型后,OxyPlot鼠标事件处理程序(例如mySeries.MouseDown)在一瞬间没有被捕获。
详细:我以一种非传统的方式使用OxyPlot库。我正在模仿在后台播放视频,快速更新占据整个图形的图像注释。这允许我使用鼠标事件在图像上绘图。我的问题是视频/图像注释播放和鼠标事件分开工作,但是当“框架更新”期间发生鼠标事件时。其中一些人错过了。我的信念是,当绘图无效myModel.InvalidatePlot(true / false)时,在模型更新之前不会拾取鼠标事件。
答案 0 :(得分:0)
我发现InvalidatePlot导致PlotView从未捕获鼠标按钮事件(例如OnMouseDown(MouseButtonEventArgs e))的问题。为了解决这个问题,我使用了另一个WPF对象来捕获鼠标事件并强制调用我的PlotView的鼠标处理方法:
1)我在另一个ZIndex级别添加了WPF Grid。并附加到鼠标事件(MouseDown,MouseWheel等)的函数:
<Grid x:Name="Grid_MouseCatcher"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Panel.ZIndex="2"
MouseDown="Grid_MouseCatcher_MouseDown"
MouseEnter="Grid_MouseCatcher_MouseEnter"
MouseLeave="Grid_MouseCatcher_MouseLeave"
MouseMove="Grid_MouseCatcher_MouseMove"
MouseUp="Grid_MouseCatcher_MouseUp"
MouseWheel="Grid_MouseCatcher_MouseWheel"
Opacity="0.0"
PreviewMouseMove="SetFocusToOxyPlot" />
<oxy:PlotView x:Name="PlotView"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Panel.ZIndex="1"
Model="{Binding PlotModel}" />
2)网格处理的每个事件都会调用我在OxyPlot源代码中创建的公共方法:
/// <summary>
/// Sends mouse events from the overlaying grid to the PlotView. Forcing an Action.
/// This was included due to an OxyPlot bug where the OnMouse... methods were not being called
/// when the plot was invalidated via InvalidatePlot(...)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Grid_MouseCatcher_MouseDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("MouseCatcher - Down: " + e.GetPosition(Grid_MouseCatcher).X + " " + e.GetPosition(Grid_MouseCatcher).Y);
PlotView.ForceMouseDown(e);
}
3)在源代码文件 OxyPlot.Wpf \ PlotBase.Events.cs 中我创建了一些函数(例如ForceMouseDown(MouseButtonEventArgs e)),它们显式调用受保护的鼠标事件(OnMouseDown(MouseButtonEventArgs e) ))
/// <summary>
/// Forces a call to Mouse handler.
/// This was needed because the events were getting lost when the model was updating
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
public void ForceMouseDown(MouseButtonEventArgs e){
this.OnMouseDown(e);
}
/// <summary>
/// Invoked when an unhandled MouseDown attached event reaches an element in its route that is derived from this class.
/// Implement this method to add class handling for this event.
/// </summary>
/// <param name="e">The <see cref="T:System.Windows.Input.MouseButtonEventArgs" /> that contains the event data.
/// This event data reports details about the mouse button that was pressed and the handled state.</param>
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
if (e.Handled)
{
return;
}
this.Focus();
this.CaptureMouse();
// store the mouse down point, check it when mouse button is released to determine if the context menu should be shown
this.mouseDownPoint = e.GetPosition(this).ToScreenPoint();
e.Handled = this.ActualController.HandleMouseDown(this, e.ToMouseDownEventArgs(this));
}
通过这种方式修复问题,我仍然可以按照OxyPlot建议的方式将鼠标事件处理程序添加到我的Plotview中,因为它们的OnMouse ####事件仍然被调用,它们现在只是由覆盖网格显式调用。 / p>
答案 1 :(得分:0)
我找到了一个更简单的解决方案,基于CodyF的解决方案。在OxyPlot.Wpf.PlotBase中的OnApplyTemplate()末尾添加以下行:
var mouseGrid = new Grid();
mouseGrid.Background = Brushes.Transparent; // background must be set for hit test to work
this.grid.Children.Add(mouseGrid);
然而,这种变化目前会制动工具提示。另请参阅OxyPlot的github页面中的pull request。