Click here to Skip to main content
Click here to Skip to main content

Custom Silverlight TextBox with contextmenu (Cut, Copy, Paste and Delete)

, 30 Mar 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
This article describes a basic functionality of textbox with cut, copy, paste and delete using context menu which might be helpful to enrich user experience and assist developers.

Introduction

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

This article describes a basic functionality of textbox with cut, copy, paste and delete using context menu which might be helpful to enrich user experience and assist developers.
By default, Silverlight does not provide a context menu.
first.JPG
Second.JPG

This article is an attempt to solve the interesting but important problem in Silverlight textbox.
Also works as both plug-in Silverlight and out of browser..

Background

Silverlight 4 now enables MouseRightButtonUp/Down events to attach and handle. This allows the developer to take control over what he/she likes to do when those events occur (for example, context style menus functionality within the application).

Third.JPG
However, context menu is not provided by Silverlight because it requires to be user initiated called by an application in response to user input. More details can be found at Security Overview of Silverlight 4.

Using the Code

<CustomPlaceHolder> Class

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           //

This abstract base class is used to create a popup menu irrespective of what kind of controls are going to be placed inside. This just acts as a placeholder or could be called a container.

<CustomContextMenu : CustomPlaceHolder> Class

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);
        }        

The CustomContextMenu class inherits from CustomPlaceHolder class and implements GetContent() of base class. In derived class AddToListBox() function will set the type of control which is going to display inside popup menu. Currently, I am using TextBlock control to display as ListBox content.

<CustomTextBox > Class

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();
        }
}

Here, CustomTextBox class derived from TextBox control provides context menu when user right clicks inside textbox. And to Setfocus (blink cursor when user clicks inside textbox) on customtextbox, we have to override OnGotFocus() function.

In this class, CustomContextMenu uses as member variable and gets initialized and gets active when right clicking inside textbox (MouseRightButtonDown/Up event).
To fire MouseRightButtonDown event make sure inside the event MouseRightButtonUp e.handled=true is set, else it won’t fire the event.

An important note: Just add this tag <body id="htmlBody"> to *.aspx page where Silverlight control is hosted. As in the above class, to track the “mousedown” event which will help to close the context menu when user clicks outside the Silverlight control (i.e on aspx/HTML page).

For those who are new to Silverlight and want to run out-of browser application, here are a few ways:

  1. Either right click on the application or click on “Install” button (If this is not installed on local machine will enable, else disable).

    Fourth.JPG

  2. Once clicked, it will pop-up a Security warning. Click on install.

    Fifth.JPG

  3. After this GoTo - Start-> All Programs: will display the below image:

    Sixth.JPG

Further Reading

History

  • 30th March, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Anil_Saran
Software Developer (Senior)
India India
No Biography provided

Comments and Discussions

 
QuestionSilverlight Toolkit? PinmemberBillVo26-Oct-11 13:01 
AnswerRe: Silverlight Toolkit? PinmemberAnil_Saran15-Nov-11 18:30 
GeneralPopupMenu Class PinmemberZiad J.khan24-May-10 9:16 
GeneralMy vote of 1 PinmemberVickyC#22-Apr-10 2:29 
GeneralCopy Paste SHape object. PinmemberAnil Pandey13-Apr-10 21:19 
GeneralRe: Copy Paste SHape object. PinmemberAnil_Saran14-Apr-10 21:52 
GeneralRe: Copy Paste SHape object. PinmemberAnil Pandey14-Apr-10 21:54 
GeneralRe: Copy Paste SHape object. PinmemberAnil_Saran14-Apr-10 21:57 
GeneralGood concept..This idea can be used for developing other rich user controls PinmemberSureshGubba31-Mar-10 0:31 
GeneralRe: Good concept..This idea can be used for developing other rich user controls PinmemberAnil_Saran3-Apr-10 2:25 
GeneralNice Article. PinmemberSumi .D30-Mar-10 19:09 
GeneralRe: Nice Article. PinmemberAnil_Saran3-Apr-10 2:25 
Generalreally a great article, thank you. what about a drop-shadow for the menu? (btw, what is "custome"? please correct it.) PinmemberMohammad Elsheimy30-Mar-10 10:11 
GeneralRe: really a great article, thank you. what about a drop-shadow for the menu? (btw, what is "custome"? please correct it.) PinmemberAnil_Saran3-Apr-10 2:24 
GeneralRe: really a great article, thank you. what about a drop-shadow for the menu? (btw, what is "custome"? please correct it.) PinmemberMohammad Elsheimy3-Apr-10 5:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150123.1 | Last Updated 30 Mar 2010
Article Copyright 2010 by Anil_Saran
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid