调用上下文菜单打开
我需要做一些像 Google 地图那样的事情(但在 WPF
中):
- 当在地图上
RightClick
时,我有一个 ContextMenu。 - 当
RightDoubleClicking
时,我有 UnZoom 操作。
所以,显然,这在 WPF 中有点困难...... 经过一番努力和搜索后,读到有人抱怨“我们无法预测未来”(我问自己 Google 如何预测未来),我决定“等待”SystemInformation.DoubleClickTime 并且只然后显示上下文菜单。
当然,这并不理想,甚至是人类可观察到的,但我不知道其他方法。
所以,我对以下代码的问题是(我有一个自定义画布):
ContextMenuEventArgs lastContextMenuEventArgs = null;
bool? lastContextMenuEventArgsHandled = null;
protected override void OnContextMenuOpening(ContextMenuEventArgs e)
{
lastContextMenuEventArgs = e;
lastContextMenuEventArgsHandled = e.Handled;
e.Handled = true;
//base.OnContextMenuOpening(e);
}
bool rightMouseClickedOnce = false;
protected override void OnPreviewMouseRightButtonUp(MouseButtonEventArgs e)
{
//base.OnPreviewMouseRightButtonUp(e);
Console.WriteLine(">>>>>>>>>>> OnPreviewMouseRightButtonUp");
if (!rightMouseClickedOnce)
{
rightMouseClickedOnce = true;
Thread thread = new Thread(
new System.Threading.ThreadStart(
delegate()
{
Thread.Sleep(System.Windows.Forms.SystemInformation.DoubleClickTime);
this.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Background,
new Action(
delegate()
{
if (rightMouseClickedOnce)
{
Console.WriteLine(">>>>>>>>>>> Right Click");
rightMouseClickedOnce = false;
base.OnPreviewMouseRightButtonUp(e);
if (lastContextMenuEventArgsHandled.HasValue)
{
Console.WriteLine(">>>>>>>>>>> lastContextMenuEventArgsHandled");
lastContextMenuEventArgs.Handled = lastContextMenuEventArgsHandled.Value;
base.OnContextMenuOpening(lastContextMenuEventArgs);
lastContextMenuEventArgsHandled = null;
}
//if (this.ContextMenu != null)
//{
// this.ContextMenu.PlacementTarget = this;
// this.ContextMenu.IsOpen = true;
//}
}
}
));
}
));
thread.Start();
}
else if (rightMouseClickedOnce)
{
Console.WriteLine(">>>>>>>>>>> Right Double Click");
rightMouseClickedOnce = false;
base.OnPreviewMouseRightButtonUp(e);
this.OnMouseRightDoubleClick(e);
}
}
一切都很好,但有一点问题:base.OnContextMenuOpening(lastContextMenuEventArgs);
似乎不起作用...
我之前设置过
if (this.ContextMenu != null)
{
this.ContextMenu.PlacementTarget = this;
this.ContextMenu.IsOpen = true;
}
并且有效,但最终这会阻止子 contextMenu 元素打开,并始终打开父(画布)contextMenu。
我可以只调用 contextMenu 事件吗?
I need to do something like Google Maps does (but in WPF
):
- when
RightClick
on the map I have a ContextMenu. - when
RightDoubleClicking
I have the UnZoom action.
So, apparently, this is a little difficult in WPF...
After struggling and searching a lot, read people that compains that "we can't predict the future" (I ask myself how does Google predict it), I decided to "wait" SystemInformation.DoubleClickTime and only then display a contextMenu.
Surely, this is not ideal, even human-observable, but I don't know other method.
So, the problem that I have with the following code is (I have a custom Canvas):
ContextMenuEventArgs lastContextMenuEventArgs = null;
bool? lastContextMenuEventArgsHandled = null;
protected override void OnContextMenuOpening(ContextMenuEventArgs e)
{
lastContextMenuEventArgs = e;
lastContextMenuEventArgsHandled = e.Handled;
e.Handled = true;
//base.OnContextMenuOpening(e);
}
bool rightMouseClickedOnce = false;
protected override void OnPreviewMouseRightButtonUp(MouseButtonEventArgs e)
{
//base.OnPreviewMouseRightButtonUp(e);
Console.WriteLine(">>>>>>>>>>> OnPreviewMouseRightButtonUp");
if (!rightMouseClickedOnce)
{
rightMouseClickedOnce = true;
Thread thread = new Thread(
new System.Threading.ThreadStart(
delegate()
{
Thread.Sleep(System.Windows.Forms.SystemInformation.DoubleClickTime);
this.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Background,
new Action(
delegate()
{
if (rightMouseClickedOnce)
{
Console.WriteLine(">>>>>>>>>>> Right Click");
rightMouseClickedOnce = false;
base.OnPreviewMouseRightButtonUp(e);
if (lastContextMenuEventArgsHandled.HasValue)
{
Console.WriteLine(">>>>>>>>>>> lastContextMenuEventArgsHandled");
lastContextMenuEventArgs.Handled = lastContextMenuEventArgsHandled.Value;
base.OnContextMenuOpening(lastContextMenuEventArgs);
lastContextMenuEventArgsHandled = null;
}
//if (this.ContextMenu != null)
//{
// this.ContextMenu.PlacementTarget = this;
// this.ContextMenu.IsOpen = true;
//}
}
}
));
}
));
thread.Start();
}
else if (rightMouseClickedOnce)
{
Console.WriteLine(">>>>>>>>>>> Right Double Click");
rightMouseClickedOnce = false;
base.OnPreviewMouseRightButtonUp(e);
this.OnMouseRightDoubleClick(e);
}
}
Everything works great but a little problem: base.OnContextMenuOpening(lastContextMenuEventArgs);
does not seem to work...
I set before
if (this.ContextMenu != null)
{
this.ContextMenu.PlacementTarget = this;
this.ContextMenu.IsOpen = true;
}
and that worked, but finally this blocks child contextMenu elements from opening, and open always the parent (canvas) contextMenu.
Can I just invoke the contextMenu event?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我对 WPF 不太了解,但是您能否显示菜单,例如距光标一个像素,并查看用户是否在同一位置以及在系统双击时间内再次右键单击?我曾经在游戏中使用过类似的技术,而且效果很好。
菜单“淡入”(也可以选择淡出)动画可以让它变得更好。
I don't know much about WPF, but can you show the menu, say, a pixel away from the cursor and see if the user right-clicks again in the same spot and in the system double click time? I've used a similar technique once in a game and it performed nice enough.
A menu "fade in" (optionally, out, too) animation could make it even better.