Introduction
- Silverlight 4 (Beta)
- VS2010 (Beta)
- .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.
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).
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
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:
- Either right click on the application or click on “Install” button (If this is not installed on local machine will enable, else disable).
- Once clicked, it will pop-up a Security warning. Click on install.
- After this GoTo - Start-> All Programs: will display the below image:
Further Reading
History
- 30th March, 2010: Initial post