65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (14投票s)

2010年3月30日

CPOL

2分钟阅读

viewsIcon

68582

downloadIcon

874

本文描述了带有剪切、复制、粘贴和删除功能的 TextBox 的基本功能,它可以通过上下文菜单实现,这可能有助于改善用户体验并协助开发人员。

引言

  1. Silverlight 4 (Beta)
  2. VS2010 (Beta)
  3. .NET Framework 4.0 (Beta)

本文描述了带有剪切、复制、粘贴和删除功能的 TextBox 的基本功能,它可以通过上下文菜单实现,这可能有助于改善用户体验并协助开发人员。
默认情况下,Silverlight 不提供上下文菜单。
first.JPG
Second.JPG

本文旨在解决 Silverlight TextBox 中的一个有趣但重要的难题。
同样适用于插件 Silverlight 和脱机浏览器环境。

背景

Silverlight 4 现在启用了 MouseRightButtonUp/Down 事件的附加和处理。 这允许开发人员控制在这些事件发生时他们想要执行的操作(例如,在应用程序内的上下文样式菜单功能)。

Third.JPG
但是,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 并希望运行脱机浏览器应用程序的人,这里有一些方法

  1. 右键单击应用程序或单击“安装”按钮(如果未安装在本地机器上,则启用,否则禁用)。

    Fourth.JPG

  2. 单击后,将弹出一个安全警告。 单击安装。

    Fifth.JPG

  3. 之后,转到 - 开始 -> 所有程序:将显示下图

    Sixth.JPG

延伸阅读

历史

  • 2010 年 3 月 30 日:初始帖子
© . All rights reserved.