1、Show a context menu:
鼠标右键单击图片会显示一个 上下文菜单 (context menu)。使用手势,如 press-and-hould 手势也会触发显示这个菜单。
右键单击应用中的图片(类似于word文档的图标),会在图片的上面显示这个上下文菜单。
图片的 xaml :
<Image x:Name="AttachmentImage" Grid.Row="1" HorizontalAlignment="Left" Stretch="None" Source="Assets/attachment.png" RightTapped="AttachmentImage_RightTapped"/> //右键单击 或者 手指按住保持 //用来显示命令执行的状态 <TextBlock x:Name="OutputTextBlock" TextWrapping="Wrap"/>
相应的 C# 代码:
private async void AttachmentImage_RightTapped(object sender, RightTappedRoutedEventArgs e) { // 向菜单中添加按钮,并且指定命令的回调 // 因为命令的委托是独一无二的,不需要指定命令id。 var menu = new PopupMenu(); menu.Commands.Add(new UICommand("Open with", (command) => { // command.Label : 获取或设置命令的标签。 OutputTextBlock.Text = "'" + command.Label + "' selected"; })); menu.Commands.Add(new UICommand("Save attachment", (command) => { OutputTextBlock.Text = "'" + command.Label + "' selected"; })); // menu.ShowForSelectionAsync() : 显示指定选择上方的上下文菜单。如果未调用命令将返回 null。 var chosenCommand = await menu.ShowForSelectionAsync(GetElementRect((FrameworkElement)sender)); if (chosenCommand == null) { //菜单隐藏时, 没有调用命令, } } //获取当前图片所占用的矩形区域 public static Rect GetElementRect(FrameworkElement element) { //返回变换对象,该变换对象可用于将 UIElement 中的坐标变换为指定的对象。 GeneralTransform buttonTransform = element.TransformToVisual(null); // 变换指定的点并返回结果。 Point point = buttonTransform.TransformPoint(new Point()); return new Rect(point, new Size(element.ActualWidth, element.ActualHeight)); }
2、Replace a default context menu :
本示例讲述了,根据选择文本框中的文字之后,对选择文字弹出上下文菜单,效果如图:
文本框的 xaml :
<TextBox x:Name="ReadOnlyTextBox" Grid.Row="1" IsReadOnly="True" TextWrapping="Wrap" Text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." // 在系统处理显示上下文菜单的交互时发生。 ContextMenuOpening="ReadOnlyTextBox_ContextMenuOpening"/>
相应的 C# :
private async void ReadOnlyTextBox_ContextMenuOpening(object sender, ContextMenuEventArgs e) { e.Handled = true; TextBox textbox = (TextBox)sender; if (textbox.SelectionLength > 0) { // 创建一个菜单并且为添加的命令指定一个id值,从而取代为每个命令指定委托。 var menu = new PopupMenu(); menu.Commands.Add(new UICommand("Copy", null, 1)); menu.Commands.Add(new UICommandSeparator()); menu.Commands.Add(new UICommand("Highlight", null, 2)); menu.Commands.Add(new UICommand("Look up", null, 3)); // 调用下面的 GetTextboxSelectionRect 方法,返回选择文字的矩形代表选择区域。 // 注意:这段代码只处理与一行文本框。如果一个文本框有多个行, //按照惯例,应该把上下文菜单放置在光标/指针位置
Rect rect = GetTextboxSelectionRect(textbox); //为选择内容选择上下文菜单 var chosenCommand = await menu.ShowForSelectionAsync(rect); if (chosenCommand != null) { switch ((int)chosenCommand.Id) { case 1:
String selectedText = ((TextBox)sender).SelectedText; var dataPackage = new DataPackage(); dataPackage.SetText(selectedText); Clipboard.SetContent(dataPackage); OutputTextBlock.Text = "'" + chosenCommand.Label + "'(" + chosenCommand.Id.ToString() + ") selected; '"
+ selectedText + "' copied to clipboard"; break; case 2: OutputTextBlock.Text = "'" + chosenCommand.Label + "'(" + chosenCommand.Id.ToString() + ") selected"; break; case 3: OutputTextBlock.Text = "'" + chosenCommand.Label + "'(" + chosenCommand.Id.ToString() + ") selected"; break; } } else { //上下文菜单消失时进行处理 } } else { //因为没有选中文本内容,所以不会显示上下文菜单 } }
//返回一个矩形为选中的文本 private Rect GetTextboxSelectionRect(TextBox textbox) { Rect rectFirst, rectLast; if (textbox.SelectionStart == textbox.Text.Length) {
// 摘要:
// 以指定的字符索引返回字符前边缘或后边缘的矩形区域。
// 参数:
// charIndex:
// 要检索其边框的字符的索引,该索引从零开始。
// trailingEdge:
// 如果获取后边缘,则为 true;如果获取前边缘,则为 false。
//
// 返回结果:
// 指定索引处字符边缘的边框。 rectFirst = textbox.GetRectFromCharacterIndex(textbox.SelectionStart - 1, true); } else { rectFirst = textbox.GetRectFromCharacterIndex(textbox.SelectionStart, false); } int lastIndex = textbox.SelectionStart + textbox.SelectionLength; if (lastIndex == textbox.Text.Length) { rectLast = textbox.GetRectFromCharacterIndex(lastIndex - 1, true); } else { rectLast = textbox.GetRectFromCharacterIndex(lastIndex, false); } GeneralTransform buttonTransform = textbox.TransformToVisual(null); Point point = buttonTransform.TransformPoint(new Point()); //确保我们返回一个有效的矩形如果选择是为多行 //,最终的选择是左边的开始的选择。 double x, y, dx, dy; y = point.Y + rectFirst.Top; dy = rectLast.Bottom - rectFirst.Top; if (rectLast.Right > rectFirst.Left) { x = point.X + rectFirst.Left; dx = rectLast.Right - rectFirst.Left; } else { x = point.X + rectLast.Right; dx = rectFirst.Left - rectLast.Right; } return new Rect(x, dx, y, dy); }