如何:通过 TextBox 使用自定义上下文菜单
更新:2007 年 11 月
本示例演示如何为 TextBox 定义和实现一个简单的自定义上下文菜单。
示例
以下可扩展应用程序标记语言 (XAML) 示例定义一个包含自定义上下文菜单的 TextBox 控件。
该上下文菜单是使用 ContextMenu 元素定义的。 该上下文菜单本身包含一系列 MenuItem 元素和 Separator 元素。 每个 MenuItem 元素都定义上下文菜单中的一个命令,Header 属性定义菜单命令的显示文本,Click 属性指定每个菜单项的处理程序方法。 Separator 元素仅用于在前面的菜单项与后面的菜单项之间呈现一条分隔线。
<TextBox
Name="cxmTextBox"
Grid.Row="1"
AcceptsReturn="True"
AcceptsTab="True"
VerticalScrollBarVisibility="Visible"
TextWrapping="Wrap"
>
<TextBox.ContextMenu>
<ContextMenu
Name="cxm"
Opened="CxmOpened"
>
<MenuItem
Header="Cut"
Name="cxmItemCut"
Click="ClickCut"
/>
<MenuItem
Header="Copy"
Name="cxmItemCopy"
Click="ClickCopy"
/>
<MenuItem
Header="Paste"
Name="cxmItemPaste"
Click="ClickPaste"
/>
<Separator/>
<MenuItem
Header="Select All"
Name="cxmItemSelectAll"
Click="ClickSelectAll"
/>
<MenuItem
Header="Select Current Line"
Name="cxmItemSelectLine"
Click="ClickSelectLine"
/>
<Separator/>
<MenuItem
Header="Undo Last Action"
Name="cxmItemUndo"
Click="ClickUndo"
/>
<MenuItem
Header="Redo Last Action"
Name="cxmItemRedo"
Click="ClickRedo"
/>
<Separator/>
<MenuItem
Header="Clear All Text"
Name="cxmItemClear"
Click="ClickClear"
/>
</ContextMenu>
</TextBox.ContextMenu>
This TextBox uses a simple custom context menu. The context menu can be disabled by checking
the CheckBox above, which simply sets the TextBox.ContextMenu property to null.
</TextBox>
下面的示例演示前面的上下文菜单定义的实现代码以及启用和禁用上下文菜单的代码。 Opened 事件用于根据 TextBox 的当前状态动态地启用或禁用某些命令。
若要还原默认上下文菜单,应使用 ClearValue 方法来清除 ContextMenu 属性的值。 若要完全禁用上下文菜单,应将 ContextMenu 属性设置为 null 引用(在 Visual Basic 中为 Nothing)。
Private Sub MenuChange(ByVal sender As Object, ByVal args As RoutedEventArgs)
Dim rb As RadioButton = CType(sender, RadioButton)
If myGrid.Children.Contains(cxmTextBox) Then
Select Case rb.Name
Case "rbCustom"
cxmTextBox.ContextMenu = cxm
Case "rbDefault"
'Clearing the value of the ContextMenu property
'restores the default TextBox context menu.
cxmTextBox.ClearValue(ContextMenuProperty)
Case "rbDisabled"
'Setting the ContextMenu propety to
'null disables the context menu.
cxmTextBox.ContextMenu = Nothing
End Select
Else : Return
End If
End Sub
Private Sub ClickPaste(ByVal sender As Object, ByVal args As RoutedEventArgs)
cxmTextBox.Paste()
End Sub
Private Sub ClickCopy(ByVal sender As Object, ByVal args As RoutedEventArgs)
cxmTextBox.Copy()
End Sub
Private Sub ClickCut(ByVal sender As Object, ByVal args As RoutedEventArgs)
cxmTextBox.Cut()
End Sub
Private Sub ClickSelectAll(ByVal sender As Object, ByVal args As RoutedEventArgs)
cxmTextBox.SelectAll()
End Sub
Private Sub ClickClear(ByVal sender As Object, ByVal args As RoutedEventArgs)
cxmTextBox.Clear()
End Sub
Private Sub ClickUndo(ByVal sender As Object, ByVal args As RoutedEventArgs)
cxmTextBox.Undo()
End Sub
Private Sub ClickRedo(ByVal sender As Object, ByVal args As RoutedEventArgs)
cxmTextBox.Redo()
End Sub
Private Sub ClickSelectLine(ByVal sender As Object, ByVal args As RoutedEventArgs)
Dim lineIndex As Integer = cxmTextBox.GetLineIndexFromCharacterIndex(cxmTextBox.CaretIndex)
Dim lineStartingCharIndex As Integer = cxmTextBox.GetCharacterIndexFromLineIndex(lineIndex)
Dim lineLength As Integer = cxmTextBox.GetLineLength(lineIndex)
cxmTextBox.Select(lineStartingCharIndex, lineLength)
End Sub
Private Sub CxmOpened(ByVal sender As Object, ByVal args As RoutedEventArgs)
'Only allow copy/cut if something is selected to copy/cut.
If cxmTextBox.SelectedText = "" Then
cxmItemCopy.IsEnabled = cxmItemCut.IsEnabled = False
Else
cxmItemCopy.IsEnabled = cxmItemCut.IsEnabled = True
'Only allow paste if there is text on the clipboard to paste.
If Clipboard.ContainsText() Then
cxmItemPaste.IsEnabled = True
Else
cxmItemPaste.IsEnabled = False
End If
End If
End Sub
private void MenuChange(Object sender, RoutedEventArgs ags)
{
RadioButton rb = sender as RadioButton;
if (rb == null || cxm == null) return;
switch (rb.Name)
{
case "rbCustom":
cxmTextBox.ContextMenu = cxm;
break;
case "rbDefault":
// Clearing the value of the ContextMenu property
// restores the default TextBox context menu.
cxmTextBox.ClearValue(ContextMenuProperty);
break;
case "rbDisabled":
// Setting the ContextMenu propety to
// null disables the context menu.
cxmTextBox.ContextMenu = null;
break;
default:
break;
}
}
void ClickPaste(Object sender, RoutedEventArgs args) { cxmTextBox.Paste(); }
void ClickCopy(Object sender, RoutedEventArgs args) { cxmTextBox.Copy(); }
void ClickCut(Object sender, RoutedEventArgs args) { cxmTextBox.Cut(); }
void ClickSelectAll(Object sender, RoutedEventArgs args) { cxmTextBox.SelectAll(); }
void ClickClear(Object sender, RoutedEventArgs args) { cxmTextBox.Clear(); }
void ClickUndo(Object sender, RoutedEventArgs args) { cxmTextBox.Undo(); }
void ClickRedo(Object sender, RoutedEventArgs args) { cxmTextBox.Redo(); }
void ClickSelectLine(Object sender, RoutedEventArgs args)
{
int lineIndex = cxmTextBox.GetLineIndexFromCharacterIndex(cxmTextBox.CaretIndex);
int lineStartingCharIndex = cxmTextBox.GetCharacterIndexFromLineIndex(lineIndex);
int lineLength = cxmTextBox.GetLineLength(lineIndex);
cxmTextBox.Select(lineStartingCharIndex, lineLength);
}
void CxmOpened(Object sender, RoutedEventArgs args)
{
// Only allow copy/cut if something is selected to copy/cut.
if (cxmTextBox.SelectedText == "")
cxmItemCopy.IsEnabled = cxmItemCut.IsEnabled = false;
else
cxmItemCopy.IsEnabled = cxmItemCut.IsEnabled = true;
// Only allow paste if there is text on the clipboard to paste.
if (Clipboard.ContainsText())
cxmItemPaste.IsEnabled = true;
else
cxmItemPaste.IsEnabled = false;
}