显示浮动线时跟踪鼠标点击
Tracking mouse clicks while displaying a floating line
试图找到一个很好的表达方式。所以,我的代码在双击时在航海图上放置了一个航路点。放下第一个航路点后,我想在航路点和鼠标光标位置之间创建一条线。这似乎是可行的,但在绘制线之后,我无法再与地图进行交互或删除任何其他 waypoints。双击事件不会触发,因为线程似乎不断地在 mouse_move 上重新绘制线条,这是 StackPanel 上的一个事件。
public async void _navigationChartPanel_MouseMove(object sender, MouseEventArgs e)
{
foreach (var element in _panelChart.Children)
{
if (element is Line && ((Line)element).Name == "RangeBearingLine")
{
index = _panelChart.Children.IndexOf(element);
break;
}
}
if (index >= 0)
{
_panelChart.Children.RemoveAt(index);
}
var line = new Line
{
Name = "RangeBearingLine",
StrokeThickness = 1,
Stroke = System.Windows.Media.Brushes.Red,
X1 = _parent._routePlanner.lastWaypointLoc.X,
Y1 = _parent._routePlanner.lastWaypointLoc.Y,
X2 = mouseClick.X,
Y2 = mouseClick.Y
};
_panelChart.Children.Add(line);
据我了解,我需要在控件下方显示该行,该行仍然可见但不妨碍我与 UI 进行交互。我不是 WPF 专家,但除了一遍又一遍地触发 MouseMove 事件之外,我想不出另一种方法来显示鼠标后的线条。有没有更好的方法?
解决此问题的一种方法是在您创建的子元素上将 IsHitTesting 设置为 false。一种更简单的方法是拦截 PreviewMouseDown,因为这是一个隧道事件,因此将在子控件之前为父控件调用:
<Canvas x:Name="theCanvas" Background="CornflowerBlue" PreviewMouseDown="Canvas_MouseDown" PreviewMouseMove="Canvas_MouseMove">
<Rectangle Canvas.Left="100" Canvas.Top="100" Width="200" Height="200" Fill="Green" /> <!-- to show that it will also work when you click on other children -->
</Canvas>
然后在你的主 window class:
public partial class MainWindow : Window
{
private Line CurrentLine;
public MainWindow()
{
InitializeComponent();
}
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
var pos = e.GetPosition(theCanvas);
if (e.ClickCount == 2)
{
this.CurrentLine = new Line
{
Name = "RangeBearingLine",
StrokeThickness = 1,
Stroke = System.Windows.Media.Brushes.Red,
X1 = pos.X,
Y1 = pos.Y,
X2 = pos.X,
Y2 = pos.Y
};
theCanvas.Children.Add(this.CurrentLine);
e.Handled = true;
}
else if ((e.ClickCount == 1) && (this.CurrentLine != null))
{
this.CurrentLine.X2 = pos.X;
this.CurrentLine.Y2 = pos.Y;
this.CurrentLine = null;
e.Handled = true;
}
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (this.CurrentLine == null)
return;
var pos = e.GetPosition(theCanvas);
this.CurrentLine.X2 = pos.X;
this.CurrentLine.Y2 = pos.Y;
e.Handled = true;
}
}
试图找到一个很好的表达方式。所以,我的代码在双击时在航海图上放置了一个航路点。放下第一个航路点后,我想在航路点和鼠标光标位置之间创建一条线。这似乎是可行的,但在绘制线之后,我无法再与地图进行交互或删除任何其他 waypoints。双击事件不会触发,因为线程似乎不断地在 mouse_move 上重新绘制线条,这是 StackPanel 上的一个事件。
public async void _navigationChartPanel_MouseMove(object sender, MouseEventArgs e)
{
foreach (var element in _panelChart.Children)
{
if (element is Line && ((Line)element).Name == "RangeBearingLine")
{
index = _panelChart.Children.IndexOf(element);
break;
}
}
if (index >= 0)
{
_panelChart.Children.RemoveAt(index);
}
var line = new Line
{
Name = "RangeBearingLine",
StrokeThickness = 1,
Stroke = System.Windows.Media.Brushes.Red,
X1 = _parent._routePlanner.lastWaypointLoc.X,
Y1 = _parent._routePlanner.lastWaypointLoc.Y,
X2 = mouseClick.X,
Y2 = mouseClick.Y
};
_panelChart.Children.Add(line);
据我了解,我需要在控件下方显示该行,该行仍然可见但不妨碍我与 UI 进行交互。我不是 WPF 专家,但除了一遍又一遍地触发 MouseMove 事件之外,我想不出另一种方法来显示鼠标后的线条。有没有更好的方法?
解决此问题的一种方法是在您创建的子元素上将 IsHitTesting 设置为 false。一种更简单的方法是拦截 PreviewMouseDown,因为这是一个隧道事件,因此将在子控件之前为父控件调用:
<Canvas x:Name="theCanvas" Background="CornflowerBlue" PreviewMouseDown="Canvas_MouseDown" PreviewMouseMove="Canvas_MouseMove">
<Rectangle Canvas.Left="100" Canvas.Top="100" Width="200" Height="200" Fill="Green" /> <!-- to show that it will also work when you click on other children -->
</Canvas>
然后在你的主 window class:
public partial class MainWindow : Window
{
private Line CurrentLine;
public MainWindow()
{
InitializeComponent();
}
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
var pos = e.GetPosition(theCanvas);
if (e.ClickCount == 2)
{
this.CurrentLine = new Line
{
Name = "RangeBearingLine",
StrokeThickness = 1,
Stroke = System.Windows.Media.Brushes.Red,
X1 = pos.X,
Y1 = pos.Y,
X2 = pos.X,
Y2 = pos.Y
};
theCanvas.Children.Add(this.CurrentLine);
e.Handled = true;
}
else if ((e.ClickCount == 1) && (this.CurrentLine != null))
{
this.CurrentLine.X2 = pos.X;
this.CurrentLine.Y2 = pos.Y;
this.CurrentLine = null;
e.Handled = true;
}
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (this.CurrentLine == null)
return;
var pos = e.GetPosition(theCanvas);
this.CurrentLine.X2 = pos.X;
this.CurrentLine.Y2 = pos.Y;
e.Handled = true;
}
}