1 Previous Next 

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




Silverlight 2 RC0 DataGrid CommittingEdit work around


In Silverlight 2 Beta 2 DataGrid had a CommittingEdit event which was a great event to update the data in an ado.net dataservice.   Unfortunately this event was removed in the RC0 of the datagrid.  As a work around Jonathan Shen suggested using a template column and using the LostFocus event to update your dataservice data.

 

 

                 <data:DataGridTemplateColumn Header="Command">
                        <data:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding FirstName}"></TextBlock>
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellTemplate>
                        <data:DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate>
                                <TextBox Text="{Binding FirstName}" LostFocus="TextBox_LostFocus"></TextBox>   //you can detect other events.
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellEditingTemplate>
                    </data:DataGridTemplateColumn>

 

Well this works fine but I don't want to have to define all my columns this way.  Sometimes it is nice to just let the datagrid autogenerate the columns. So I decided to use the DataGrid's PreparingCellForEdit to add the handler for the LostFocus event.  Couple of other things you need to do.  First Remove the old event handler so the event does not fire multiple times.  Second we need a variable to keep track of the item that was edited when the lost focus event is fired we will be on another record.

 

Dim prod As Northwind.Products

Private Sub dgProducts_PreparingCellForEdit(ByVal sender As Object, ByVal e As System.Windows.Controls.DataGridPreparingCellForEditEventArgs) Handles dgProducts.PreparingCellForEdit
    RemoveHandler e.EditingElement.LostFocus, AddressOf Textbox_LostFocus
    AddHandler e.EditingElement.LostFocus, AddressOf Textbox_LostFocus
    prod = DirectCast(dgProducts.SelectedItem, Northwind.Products)
End Sub

Friend Sub Textbox_LostFocus(ByVal sender As Object, ByVal e As EventArgs)
    proxy.UpdateObject(prod)
End Sub

 

Here is the complete code

 

Imports System.Collections.ObjectModel
Imports System.Data.Services.Client
Imports System.Diagnostics

Partial Public Class Page
    Inherits UserControl

    Public Sub New()
        InitializeComponent()
    End Sub

    Dim q As DataServiceQuery(Of Northwind.Products)
    Dim proxy As Northwind.NorthwindEntities

    Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        Dim address = New Uri(Application.Current.Host.Source, "../WebDataService1.svc")

        proxy = New Northwind.NorthwindEntities(address)

        Dim qry = From p In proxy.Products Select p
        q = CType(qry, Global.System.Data.Services.Client.DataServiceQuery(Of Northwind.Products))

        q.BeginExecute(AddressOf ProductsLoaded, Nothing)

    End Sub

    Friend Sub ProductsLoaded(ByVal ar As System.IAsyncResult)
        Dim c = q.EndExecute(ar)
        Dim d As New ObservableCollection(Of Northwind.Products)
        For Each p In c
            d.Add(p)
        Next
        Dim GetOnRightThread As New SetTheDataSource(AddressOf SetDataSource)
        Dispatcher.BeginInvoke(GetOnRightThread, New Object() {d})
    End Sub

    Delegate Sub SetTheDataSource(ByVal d As ObservableCollection(Of Northwind.Products))

    Friend Sub SetDataSource(ByVal d As ObservableCollection(Of Northwind.Products))
        dgProducts.ItemsSource = d
    End Sub

    Dim prod As Northwind.Products

    Private Sub dgProducts_PreparingCellForEdit(ByVal sender As Object, ByVal e As System.Windows.Controls.DataGridPreparingCellForEditEventArgs) Handles dgProducts.PreparingCellForEdit
        RemoveHandler e.EditingElement.LostFocus, AddressOf Textbox_LostFocus
        AddHandler e.EditingElement.LostFocus, AddressOf Textbox_LostFocus
        prod = DirectCast(dgProducts.SelectedItem, Northwind.Products)
    End Sub

    Friend Sub Textbox_LostFocus(ByVal sender As Object, ByVal e As EventArgs)
        proxy.UpdateObject(prod)
    End Sub

    Friend Sub SaveComplete(ByVal ar As System.IAsyncResult)
        proxy.EndSaveChanges(ar)
    End Sub

    Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnSave.Click
        proxy.BeginSaveChanges(AddressOf SaveComplete, Nothing)
    End Sub
End Class


kick it on DotNetKicks.com



Silverlight 2.0 Interacting with html


With SilverLight 2.0 you can interact and handle events with the html elements on your page.  Here is a simple example that places a select (drop down control) on a web page which will change the color of a ellipse on a SilverLight app.  So lets start with the html

 

<body style="height: 100%; margin: 0;">
    <form id="form1" runat="server" style="height: 100%;">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <br />
    <span>Select a Color </span>
    <select id="ddColor">
        <option>Red</option>
        <option>Blue</option>
        <option>Green</option>
    </select>
    <br />
    <br />
    <div style="height: 100%;">
        <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/HtmlAndSilverlight.xap"
            MinimumVersion="2.0.30923.0" Width="100%" Height="100%" />
    </div>
    </form>
</body>

 

 

Now the XAML

 

<UserControl x:Class="HtmlAndSilverlight.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
    <Canvas x:Name="LayoutRoot" Background="Tan" >
        <Ellipse x:Name="el" Width="400" Height="300" Fill="Red"></Ellipse>
    </Canvas>
</UserControl>

 

 

Now build the app so we have intellisense for the controls.  Ok first off lets get access to the drop down (select) on the web page. Then we can use AttachEvent to handle the onchange event.   

 

Dim cbo As HtmlElement
Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    cbo = HtmlPage.Document.GetElementById("ddColor")
    cbo.AttachEvent("onchange", AddressOf ColorChanged)
End Sub

 

Once the user selects a color we will change the color of the ellipse.  Here is the complete code listing

 

Imports System.Windows.Browser

Partial Public Class Page
    Inherits UserControl

    Public Sub New()
        InitializeComponent()
    End Sub
    Dim cbo As HtmlElement
    Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        cbo = HtmlPage.Document.GetElementById("ddColor")
        cbo.AttachEvent("onchange", AddressOf ColorChanged)
    End Sub

    Private Sub ColorChanged(ByVal sender As Object, ByVal e As HtmlEventArgs)
        Dim x = CInt(cbo.GetAttribute("selectedIndex").ToString)
        Select Case x
            Case 0
                el.Fill = New SolidColorBrush(Colors.Red)
            Case 1
                el.Fill = New SolidColorBrush(Colors.Blue)
            Case 2
                el.Fill = New SolidColorBrush(Colors.Green)
        End Select
    End Sub
End Class

 

Hope this helps




AspNet: Adding Silverlight 1.0 to an Asp.Net project


Silverlight 1.0 is a new Web 2.0 technology for using a subset of WPF on a webpage. 

 

You can interact with the WPF controls with JavaScript.  Silverlight 1.1 will allow you to program with VB but you will have to wait for VS 2008 to be released to use it. 

 

There are versions of Silverlight 1.0 for Windows and Mac pc's. Moonlight is a version that runs on Linux based pc's.

 

http://silverlight.net/GetStarted/

 

http://www.mono-project.com/Moonlight

 

To start off with you need to download and install the Silverlight 1.0 sdk on the Silverlight get started page. 

Then do the following steps.

Step 1.


Add the Silverlight.js and CreateSilverlight.js files found in the Silverlight SDK resources directory to your project.

 

Step 2.

Register the JavaScript files on the page.

<head runat="server">
    <title>Untitled Page</title>
    <script type="text/javascript" src="Silverlight.js"></script>
    <script type="text/javascript" src="createSilverlight.js"></script>
</head>

 

For a webpage which uses ajax you have to register the files with the ScriptManager

            <asp:ScriptManager ID="sm1" EnablePartialRendering="true" runat="server">
                <Scripts>
                    <asp:ScriptReference Path="Silverlight.js" />
                    <asp:ScriptReference Path="CreateSilverlight.js" />
                </Scripts>
            </asp:ScriptManager>

Step 3

Create an Xaml page.  Add an xml file to your project and name it myxaml.xaml

 

This xaml page just shows a circle

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

  <Ellipse
     Height="200" Width="200"
     Stroke="Black" StrokeThickness="10" Fill="SlateBlue" />
</Canvas>

For more examples see the Silverlight SDK

 

Step 4

Create the Silverlight control on your webpage.  Note the div which hosts the silverlight control must be before the javascript for the control to load.

 

    <div id="mySilverlightPluginHost">
    </div>
    <script type="text/javascript">
       
       
        // Retrieve the div element you created in the previous step.
        var parentElement =
            document.getElementById("mySilverlightPluginHost");
       
        // This function creates the Silverlight plugin.
        createMySilverlightPlugin();
        function createMySilverlightPlugin()

    Silverlight.createObject(
        "myxaml.xaml",                  // Source property value.
        parentElement,                  // DOM reference to hosting DIV tag.
        "mySilverlightPlugin",         // Unique plugin ID value.
        {                               // Per-instance properties.
            width:'300',                // Width of rectangular region of
                                        // plugin area in pixels.
            height:'300',               // Height of rectangular region of
                                        // plugin area in pixels.
            inplaceInstallPrompt:true, // Determines whether to display
                                        // in-place install prompt if
                                        // invalid version detected.
            background:'#D6D6D6',       // Background color of plugin.
            isWindowless:'false',       // Determines whether to display plugin
                                        // in Windowless mode.
            framerate:'24',             // MaxFrameRate property value.
            version:'1.0'               // Silverlight version to use.
        },
        {
            onError:null,               // OnError property value --
                                        // event handler function name.
            onLoad:null                 // OnLoad property value --
                                        // event handler function name.
        },
        null);                          // Context value -- event handler function name.
}

    </script>

 

Run your website

 




1 Previous Next