Sunday, October 5, 2008

Silverlight 2.0 Create a context menu

Silverlight 2 does not come with a context menu control.  You could always handle the html document's oncontextmenu event and open a popcontrol to use as a context menu.  This sample should help you get started.

<UserControl x:Class="SilverlightContextMenu.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid>
        <Rectangle x:Name="LayoutRoot" Fill ="Green" ></Rectangle >
        <Popup x:Name="menu">
            <StackPanel>
                <Button x:Name="btnRed" Content="Red"></Button>
                <Button x:Name="btnWhite" Content="White"></Button>
                <Button x:Name="btnBlue" Content="Blue"></Button>
            </StackPanel>
        </Popup>
    </Grid>
</UserControl>
Imports System.Windows.Browser

Partial Public Class Page
    Inherits UserControl

    Dim WithEvents cm As ContextMenuCatcher

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub btnBlue_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnBlue.Click
        LayoutRoot.fill = New SolidColorBrush(Colors.Blue)
        menu.IsOpen = False
    End Sub

    Private Sub btnRed_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnRed.Click
        LayoutRoot.fill = New SolidColorBrush(Colors.Red)
        menu.IsOpen = False
    End Sub

    Private Sub btnWhite_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnWhite.Click
        LayoutRoot.fill = New SolidColorBrush(Colors.White)
        menu.IsOpen = False
    End Sub

    Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        cm = New ContextMenuCatcher(LayoutRoot)
        menu.IsOpen = False
    End Sub

    Private Sub cm_RightClick(ByVal sender As Object, ByVal e As RightClickEventArgs) Handles cm.RightClick
        menu.HorizontalOffset = e.AbsolutePoint.X
        menu.VerticalOffset = e.AbsolutePoint.Y
        menu.IsOpen = True
    End Sub

    Private Sub menu_MouseLeave(ByVal sender As Object, ByVal e As System.Windows.Input.MouseEventArgs) Handles menu.MouseLeave
        menu.IsOpen = False
    End Sub

End Class

Public Class ContextMenuCatcher
    Public Event RightClick(ByVal sender As Object, ByVal e As RightClickEventArgs)
    Dim ctrl As UIElement

    Public Sub New(ByVal c As UIElement)
        ctrl = c

        HtmlPage.Document.AttachEvent("oncontextmenu", AddressOf OnContextMenu)
    End Sub

    Private Sub OnContextMenu(ByVal sender As Object, ByVal e As HtmlEventArgs)
        System.Diagnostics.Debug.WriteLine(e.OffsetX.ToString)
        System.Diagnostics.Debug.WriteLine(e.OffsetY.ToString)
        Dim pt As New Point(e.OffsetX, e.OffsetY)
        e.PreventDefault()
        e.StopPropagation()
        RaiseEvent RightClick(Me, New RightClickEventArgs(ctrl, pt))
    End Sub

End Class

Public Class RightClickEventArgs

    Dim m_Source As UIElement
    Public Property Source() As UIElement
        Get
            Return m_Source
        End Get
        Set(ByVal value As UIElement)
            m_Source = value
        End Set
    End Property

    Dim m_RelativePoint As Point
    Public Property RelativePoint() As Point
        Get
            Return m_RelativePoint
        End Get
        Set(ByVal value As Point)
            m_RelativePoint = value
        End Set
    End Property

    Dim m_AbsolutePoint As Point
    Public Property AbsolutePoint() As Point
        Get
            Return m_AbsolutePoint
        End Get
        Set(ByVal value As Point)
            m_AbsolutePoint = value
        End Set
    End Property

    Friend Sub New(ByVal source As UIElement, ByVal absolutePoint As Point)
        Me.Source = source
        Me.AbsolutePoint = absolutePoint
        Me.RelativePoint = GetPosition(source)
    End Sub

    Public Function GetPosition(ByVal relativeTo As UIElement) As Point
        Dim transform As GeneralTransform = Application.Current.RootVisual.TransformToVisual(relativeTo)
        Return transform.Transform(AbsolutePoint)
    End Function
End Class
 
You also have to make the silverlight control windowless for this to work
<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightContextMenu.xap" MinimumVersion="2.0.30923.0" Width="100%" Height="100%" Windowless="true" />

No comments:

Post a Comment