InvalidatePlot が、OnMouseDown(MouseButtonEventArgs e) などのマウス ボタン イベントが PlotView によってキャプチャされないという問題を引き起こしていることがわかりました。これを回避するために、別の WPF オブジェクトを使用してマウス イベントをキャッチし、PlotView のマウス処理メソッドを強制的に呼び出しました。
1) 別の ZIndex レベルに WPF グリッドを追加しました。そして、マウス イベント (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で、保護されたマウス イベント (OnMouseDown(MouseButtonEventArgs e)) を明示的に呼び出す関数 (ForceMouseDown(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#### イベントがまだ呼び出されているため、オーバーレイ グリッドによって明示的に呼び出されるようになりました。