带有上下文菜单(剪切、复制、粘贴和删除)的自定义 Silverlight TextBox






4.64/5 (14投票s)
本文描述了带有剪切、复制、粘贴和删除功能的 TextBox 的基本功能,它可以通过上下文菜单实现,这可能有助于改善用户体验并协助开发人员。
引言
- Silverlight 4 (Beta)
- VS2010 (Beta)
- .NET Framework 4.0 (Beta)
本文描述了带有剪切、复制、粘贴和删除功能的 TextBox 的基本功能,它可以通过上下文菜单实现,这可能有助于改善用户体验并协助开发人员。
默认情况下,Silverlight 不提供上下文菜单。
本文旨在解决 Silverlight TextBox 中的一个有趣但重要的难题。
同样适用于插件 Silverlight 和脱机浏览器环境。
背景
Silverlight 4 现在启用了 MouseRightButtonUp
/Down
事件的附加和处理。 这允许开发人员控制在这些事件发生时他们想要执行的操作(例如,在应用程序内的上下文样式菜单功能)。

但是,Silverlight 不提供上下文菜单,因为它需要由应用程序在响应用户输入时调用用户启动。 更多详细信息请参见 Silverlight 4 安全概述。
Using the Code
<CustomPlaceHolder> 类
Public abstract class CustomPlaceHolder
{
private Point _location;
private bool _isShowing;
private Popup _popup;
private Grid _grid;
private FrameworkElement _content;
public void Show(Point location)
{
if (_isShowing)
throw new InvalidOperationException();
_isShowing = true;
_location = location;
DisplayPopup();
_popup.IsOpen = true;
}
public void Close()
{
_isShowing = false;
if (_popup != null)
_popup.IsOpen = false;
}
private void DisplayPopup()
{
_popup = new Popup();
_grid = new Grid();
_popup.Child = _grid;
_content = GetContent();
_content.HorizontalAlignment = HorizontalAlignment.Left;
_content.VerticalAlignment = VerticalAlignment.Top;
_content.Margin = new Thickness(_location.X, _location.Y, 0, 0);
_grid.Children.Add(_content);
}
#region Abstract and Virtual
protected abstract FrameworkElement GetContent();
protected virtual void OnClickOutside() { }
#endregion //Abstract and Virtual //
这个 abstract
基类用于创建弹出菜单,无论将哪些类型的控件放置在其中。 它只是充当占位符或可以称为容器。
<CustomContextMenu : CustomPlaceHolder> 类
Public abstract class CustomContextMenu : CustomPlaceHolder
{
protected override FrameworkElement GetContent()
{
Grid grid = new Grid()
{
Width = 100,
Height = 100
};
Border border = new Border()
{
BorderBrush = new SolidColorBrush(Colors.Black),
BorderThickness = new Thickness(1),
Background = new SolidColorBrush(Colors.LightGray)
};
_options = new ListBox();
AddToListBox();
grid.Children.Add(_options);
return grid;
}
private void AddToListBox()
{
TextBlock cut = new TextBlock()
{
Text = "Cut",
Width = 90
};
cut.MouseLeftButtonDown +=
new System.Windows.Input.MouseButtonEventHandler
(cut_MouseLeftButtonDown);
TextBlock copy = new TextBlock()
{
Text = "Copy",
Width = 90
};
copy.MouseLeftButtonDown +=
new System.Windows.Input.MouseButtonEventHandler
(copy_MouseLeftButtonDown);
TextBlock paste = new TextBlock()
{
Text = "Paste",
Width = 90
};
paste.MouseLeftButtonDown +=
new System.Windows.Input.MouseButtonEventHandler
(paste_MouseLeftButtonDown);
TextBlock delete = new TextBlock()
{
Text = "Delete",
Width = 90
};
delete.MouseLeftButtonDown +=
new System.Windows.Input.MouseButtonEventHandler
(delete_MouseLeftButtonDown);
if (string.IsNullOrEmpty(_textBox.SelectedText))
{
cut.Foreground = new SolidColorBrush(Colors.Gray);
copy.Foreground = new SolidColorBrush(Colors.Gray);
delete.Foreground = new SolidColorBrush(Colors.Gray);
}
_options.Items.Add(cut);
_options.Items.Add(copy);
_options.Items.Add(paste);
_options.Items.Add(delete);
}
CustomContextMenu
类继承自 CustomPlaceHolder
类并实现了基类的 GetContent()
。 在派生类中,AddToListBox()
函数将设置要在弹出菜单中显示的控件类型。 目前,我使用 TextBlock
控件作为 ListBox
内容显示。
<CustomTextBox > 类
Public class CustomTextBox:TextBox
{
CustomContextMenu contextMenu;
private void CustomContextMenu()
{
this.MouseRightButtonDown +=
new System.Windows.Input.MouseButtonEventHandler
(CustomTextBox_MouseRightButtonDown);
this.MouseRightButtonUp +=
new System.Windows.Input.MouseButtonEventHandler
(CustomTextBox_MouseRightButtonUp);
}
void CustomTextBox_MouseRightButtonUp
(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (contextMenu == null)
{
contextMenu = new CustomContextMenu(this);
contextMenu.Show(e.GetPosition(null));
}
else
{
contextMenu.Close();
contextMenu.Show(e.GetPosition(null));
}
}
void CustomTextBox_MouseRightButtonDown
(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
this.Focus();
e.Handled = true;
}
void Content_Resized(object sender, EventArgs e)
{
HtmlElement element = HtmlPage.Document.GetElementById("htmlBody");
if (element != null)
{
element.AttachEvent("mousedown",
new EventHandler<HtmlEventArgs>(RaiseHtmlEvent));
}
CloseCustomContextMenu();
}
}
这里,从 TextBox
控件派生的 CustomTextBox
类在用户在 textbox
内右键单击时提供上下文菜单。 为了 Setfocus
(当用户在 textbox
内单击时闪烁光标),我们必须重写 OnGotFocus()
函数。
在这个类中,CustomContextMenu
用作成员变量,并在右键单击 textbox
内部时(MouseRightButtonDown
/Up
事件)初始化并激活。
要触发 MouseRightButtonDown
事件,请确保在事件内部设置 MouseRightButtonUp e.handled=true
,否则它将不会触发该事件。
重要提示:只需将此标签 <body id="htmlBody">
添加到托管 Silverlight 控件的 *.aspx 页面中。 如上面的类中,用于跟踪“mousedown
”事件,这将有助于在用户单击 Silverlight 控件外部时关闭上下文菜单(即在 aspx/HTML 页面上)。
对于那些刚接触 Silverlight 并希望运行脱机浏览器应用程序的人,这里有一些方法
- 右键单击应用程序或单击“安装”按钮(如果未安装在本地机器上,则启用,否则禁用)。
- 单击后,将弹出一个安全警告。 单击安装。
- 之后,转到 - 开始 -> 所有程序:将显示下图
延伸阅读
历史
- 2010 年 3 月 30 日:初始帖子