Wintellect  
The preview is available for download here.  This includes the much awaited MVC support that Scott has been recently blogging about.

There are many mouse events raised in Silverlight 1.1/2.0, but you will notice that right click is not one of them.  This is because by default the Silverlight plug-in hooks the right click to show information about Silverlight and update settings.  So what do you do if you have a feature such as a context menu that relies on the right click event?  Don't fret, JavaScript interaction with managed code comes to the rescue.

First you hook the right click event with your own JavaScript function.


function click(e)
{
    var control = document.getElementById("SilverlightControl");


    if (navigator.appName == "Netscape" && e.which==3)
    {
        alert(e.clientX + " " + e.clientY);
        control.Content.PageReference.RightMouseButtonDown(e.clientX, e.clientY);
        return false;
    }


    if (navigator.appName == "Microsoft Internet Explorer" && event.button==2)
    {
        alert(event.clientX + " " + event.clientY);
        control.Content.PageReference.RightMouseButtonDown(event.clientX, event.clientY);
        return false;
    }


    return true;
}

document.onmousedown=click

Fig 1. (JavaScript) Hooking right click event and passing to managed code
 
 
In the above code snippet you get a reference to the SilverLight plug-in and from there you can call your managed code method.  So in this case the JavaScript is calling a managed code method called RightMouseButtonDown that accepts the current mouse X and Y coordinates as input parameters.
 
Next you move over to managed code.  There are two steps that need to be taken for a managed code method to be called from JavaScript.  First you will need to register the class itself as callable from JavaScript.  You do this by registering the class as a scriptable endpoint and giving it a string reference name.  This code uses "PageReference" as the string reference name since the class name is "Page". 


//Register the page class, "this", as a scriptable endpoint
WebApplication.Current.RegisterScriptableObject("PageReference", this);

Fig 2. (Managed Code) Registering the page class as a scriptable endpoint
 
 
Finally you decorate the managed code method that is to be called from JavaScript with the [Scriptable] attribute.  Once this is done the right click event will be hooked from JavaScript and passed on or "raised" to the appropriate managed code method.


[Scriptable]
public void RightMouseButtonDown(int x, int y)
{
     // Do some work here
     // such as displaying a context menu
}

Fig 3. (Managed Code) RightMouseButtonDown method decorated with [Scriptable] attribute
 
 
That's it!  Now you have a managed code method that will be called when the user clicks the right mouse button.
 

One of the things that I find myself doing over and over in Silverlight is centering text in TextBlock objects. The majority of the time I am doing this for headers, footers, and other areas where I have a single line of text. Often I find that I also need to size text within a TextBlock appropriately for the containing space. The algorithm is the same whether you do this in Silverlight 1.0 vs. 1.1, but I will show both. In figure 1 you see the XAML that we will be working with, figure 2 shows the JavaScript needed to center the text using Silvelright 1.0, and figure 3 shows the managed C# needed to center the text using Silverlight 1.1.


<Canvas x:Name="textCanvas" Width="640" Height="480"
    <TextBlock x:Name="CenteredText" 
         Text="This Text Should Be Centered."
         Width="640" Height="480" />
</Canvas>

Fig 1. XAML


var headerText = this.target.findName("CenteredText"    

while(headerText.ActualWidth > headerText.Width)
{
   
headerText.FontSize -= 0.5;
}

var newLeft = ((headerText.Width - headerText.ActualWidth) / 2)
    + this.headerText.GetValue("Canvas.Left");

headerText.SetValue("Canvas.Left", newLeft);  

var newTop = ((headerText.Height - headerText.ActualHeight) / 2)
   
+ this.headerText.GetValue("Canvas.Left");

headerText.SetValue("Canvas.Top", newTop);


Fig 2. Centering and sizing text in JavaScript


while(CenteredText.ActualWidth > CenteredText.Width)

   
CenteredText.FontSize -= 0.5;
}

double newLeft = ((CenteredText.Width - CenteredText.ActualWidth) / 2)
   
+ (double)CenteredText.GetValue(Canvas.LeftProperty);

CenteredText.SetValue(Canvas.LeftProperty, newLeft);

double newTop = ((CenteredText.Height - CenteredText.ActualHeight) / 2)
   
+ (double)CenteredText.GetValue(Canvas.TopProperty);

CenteredText.SetValue(Canvas.TopProperty, newTop);

Fig 3. Centering and sizing text in Managed C#


First findName is called to get a reference to the TextBlock object of which you are centering the text.  This step is only required in the 1.0 version; you will already have a strongly typed reference in 1.1.  Next a while loop is executes that decreases the font size of the TextBlock object until the actual width is less than or equal to the width. Next a new left and top position is calculated and set for the TextBlock object. The text is not actually centered in the TextBlock object since there is no support for centering, instead the TextBlock object itself is moved to the appropriate left and top positions to give the illusion of being centered.

In a scenario where you need to set the text property of a TextBlock repeatedly you will need to cache the initial left and top position of the object so that you have the same starting point every successive time you center the text.

There are a couple things that I think a Silverlight control base class should be doing for you. First of all it should load up the appropriate XAML from the resource collection for you. As long as you follow the naming and association convention of Namespace.ClassName.xaml this is fairly easy to do. With just a little bit of reflection code you can get the namespace and class names to build the filename from. This will end up saving you some debug cycles when you copy/paste a control to create a new control forgetting to update the string referencing the XAML file for the new control.


string
xamlFileName = string.Format("{0}.{1}.xaml"
    , this.GetType().Namespace
    , this.GetType().Name);

 

The second thing your base class should be doing for you is storing a reference to your top level Canvas object. You will then use this reference to find existing child objects such as StoryBoards, TextBlocks, or MediaElements or maybe add new controls/objects to the children collection. Whatever logic you are writing in your control, you are guaranteed to need a reference to this root object.


RootCanvas =
    (Canvas)this.InitializeFromXaml(new System.IO.StreamReader(s).ReadToEnd());

 

Hopefully this will help out. Below is the complete source for the base class.




public
class CustomControlBase : Control
{
    private Canvas _rootCanvas;
    protected Canvas RootCanvas
    {
        get { return _rootCanvas; }
        set { _rootCanvas = value; }
    }

    public
CustomControlBase()
    {
        System.IO.Stream s = LoadXamlStream();
        RootCanvas =
            (Canvas)this.InitializeFromXaml(new System.IO.StreamReader(s).ReadToEnd());
    }

    protected System.IO.Stream LoadXamlStream()
    {
        string xamlFileName = string.Format("{0}.{1}.xaml"
            , this.GetType().Namespace
            , this.GetType().Name);
        return this.GetType().Assembly.GetManifestResourceStream(xamlFileName);
    }
}

 

I am sure that I am missing a few, but this is certainly a good starting point.

·         Addicted to Digital Media

·         Barak's Blog about Silverlight and beyond

·         Building a Better User Experience

·         Come Get Some...Thoughts On Software Technology

·         Delay's Blog

·         DevDave - Dave Relyea's Blog

·         Eric Griffin's Blog

·         Even a chimp can write code

·         ExplosiveDog.Com

·         Gavin Gear's Tech Blog

·         Jaime Rodriguez

·         Jeff Prosise's Blog

·         Jesse Liberty - Silverlight Geek

·         Joe Stegman's WebBlog

·         Laurence Moroney's Web.NEXT Blog

·         Michael's Blog

·         Mike Harsh's Blog

·         Mike Taulty's Blog

·         MS MossyBlog

·         Nick on Silverlight and WPF

·         ScottGu's Blog

·         Silver Lighting - My Silverlight Blog

·         Silverlight SDK

·         Somasegar's WebLog

·         Tim Sneath

·         WynApse

Keith Rome and I presented on Silverlight last week for the Charlotte Developers Guild.  We could not have hoped for a better crowd; by my count there were close to 80 in attendance.  The theme for the night was “Silverlight Soup to Nuts”.  I presented an overview of the features available to developers in Silverlight 1.1 including animation control, interaction with the HTML DOM, use of isolated storage, calling managed code from JavaScript, custom controls, and web service interaction.  You can download the code for the talk from my recently published Silverlight article on DevX: Managed Code Shines in Silverlight 1.1.

Keith then presented on his newest Silverlight 1.1 game, Gem Blaster.  Gem Blaster uses Keith’s next generation gaming engine building on his previous game, Popper.  You can also go directly here to play the game: http://www.mindfusioncorp.com/gemblaster/.