Ed Silverton

Category: Uncategorized

Silverlight Beta 2 Service reference woes

When trying to add a Web Service reference to a Silverlight App in VS 2008 with Silverlight Tools Beta 2 installed I kept getting the really useful message “Object reference not set to an instance of an object”. Luckily this guy has the answer. Normally I try to avoid messing with program files but I thought I’d risk it and it’s worked a treat. Not only that but now VS doesn’t crash every time I close it down. Found via Tim Heuer’s blog.

A Simple Silverlight Tab Menu

Tab menus are a common design feature for many web sites. I wasn’t able to find a Tab Menu control with source anywhere so I created my own using the built in Silverlight controls. Here’s how I’ve done it:

Add a StackPanel to your Xaml page.

<StackPanel x:Name=”MainMenu” Orientation=”Horizontal” />

In the CodeBehind for that page add the following:

private void BindMenu()
{
    string[] menuItems = “Home, About Us, Products, Services, Contact”.Split(‘,’);   

    foreach (string item in menuItems)
    {
        RadioButton btn = new RadioButton();
        btn.Content = item;
        btn.Checked +=
new RoutedEventHandler(MainMenu_SelectionChanged);
        btn.GroupName =
“Main Menu”;
        btn.DataContext = item;
        btn.Margin =
new System.Windows.Thickness(0, 0, 2, 0);
        btn.Padding =
new System.Windows.Thickness(6, 6, 6, 4);
        btn.MinWidth = 60;
        btn.Style = (
Style)Application.Current.Resources["MainMenuTab"];
       
       
MainMenu.Children.Add(btn);
    }
}

void MainMenu_SelectionChanged(object sender, RoutedEventArgs e)
{
    string name = (String)((RadioButton)sender).DataContext;
}

Call the BindMenu() function from your Page_Loaded() function.

You can see that all I’m doing is getting an array of page names then iterating over them to create a RadioButton for each then adding that RadioButton to the previously defined StackPanel. The DataContext property is in this case being set to the string item but you could set this to be any complex object.

Just before adding the RadioButton to the StackPanel you can see that I’m setting it’s Style property to

Application.Current.Resources["MainMenuTab"];

This Style is contained in the App.xaml file and looks like this:

<Application.Resources>
    <Style x:Key=”MainMenuTab” TargetType=”RadioButton”>
        <Setter Property=”IsEnabled” Value=”true” />
        <Setter Property=”IsTabStop” Value=”true” />
        <Setter Property=”Foreground” Value=”Black” />
        <Setter Property=”Margin” Value=”0″ />
        <Setter Property=”MinWidth” Value=”0″ />
        <Setter Property=”HorizontalContentAlignment” Value=”Center” />
        <Setter Property=”VerticalContentAlignment” Value=”Center” />
        <Setter Property=”Cursor” Value=”Hand” />
        <Setter Property=”TextAlignment” Value=”Left” />
        <Setter Property=”TextWrapping” Value=”NoWrap” />
        <Setter Property=”FontSize” Value=”11″ />
        <Setter Property=”FontFamily” Value=”Verdana”/>
        <Setter Property=”Template”>
            <Setter.Value>
                <ControlTemplate TargetType=”RadioButton”>
                    <Grid x:Name=”RootElement” Cursor=”{TemplateBinding Cursor}”>
                        <Grid.Resources>
                            <Storyboard x:Name=”Normal State”/>
                            <Storyboard x:Name=”Checked State”>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName=”Checked” Storyboard.TargetProperty=”(UIElement.Opacity)” BeginTime=”00:00:00″ Duration=”00:00:00.1000000″>
                                    <SplineDoubleKeyFrame KeyTime=”00:00:00.1″ Value=”1″/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                            <Storyboard x:Name=”MouseOver Checked State”>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName=”Checked” Storyboard.TargetProperty=”(UIElement.Opacity)” BeginTime=”00:00:00″ Duration=”00:00:00.0000000″>
                                    <SplineDoubleKeyFrame KeyTime=”00:00:00″ Value=”1″/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                            <Storyboard x:Name=”Pressed Checked State”>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName=”Checked” Storyboard.TargetProperty=”(UIElement.Opacity)” BeginTime=”00:00:00″ Duration=”00:00:00.0000000″>
                                    <SplineDoubleKeyFrame KeyTime=”00:00:00″ Value=”1″/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                            <Storyboard x:Name=”MouseOver Unchecked State”>                                  
                               
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=”Checked” Storyboard.TargetProperty=”(UIElement.Opacity)” BeginTime=”00:00:00″ Duration=”00:00:00.5000000″>
                                    <SplineDoubleKeyFrame KeyTime=”00:00:00.1″ Value=”0.5″/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                            <Storyboard x:Name=”Pressed Unchecked State”>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName=”Checked” Storyboard.TargetProperty=”(UIElement.Opacity)” BeginTime=”00:00:00″ Duration=”00:00:00.5000000″>
                                    <SplineDoubleKeyFrame KeyTime=”00:00:00.1″ Value=”1″/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                            <Storyboard x:Name=”Disabled Unchecked State”>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName=”Unchecked” Storyboard.TargetProperty=”(Shape.Background).(SolidColorBrush.Color)” BeginTime=”00:00:00″ Duration=”00:00:00.0000000″>
                                    <SplineColorKeyFrame KeyTime=”00:00:00″ Value=”Gray”/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                            <Storyboard x:Name=”Disabled Checked State”>
                                <ColorAnimationUsingKeyFrames Storyboard.TargetName=”Unchecked” Storyboard.TargetProperty=”(Shape.Background).(SolidColorBrush.Color)” BeginTime=”00:00:00″ Duration=”00:00:00.0000000″>
                                    <SplineColorKeyFrame KeyTime=”00:00:00″ Value=”Gray”/>
                                </ColorAnimationUsingKeyFrames>
                            </Storyboard>
                        </Grid.Resources>
                        <Border x:Name=”Unchecked”
                           Opacity=”1″
                           BorderBrush=”BurlyWood”
                           BorderThickness=”1,1,1,0″
                           Background=”Beige”
                           CornerRadius=”4,4,0,0″>
                        </Border>
                        <Border x:Name=”Checked”
                           Opacity=”0″
                           BorderBrush=”BurlyWood”
                           BorderThickness=”1,1,1,0″
                           Background=”White”
                           CornerRadius=”4,4,0,0″>
                        </Border>
                        <ContentPresenter
                         Content=”{TemplateBinding Content}”
                         ContentTemplate=”{TemplateBinding ContentTemplate}”
                         Background=”Transparent”
                         FontFamily=”{TemplateBinding FontFamily}”
                         FontSize=”{TemplateBinding FontSize}”
                         FontStretch=”{TemplateBinding FontStretch}”
                         FontStyle=”{TemplateBinding FontStyle}”
                         FontWeight=”{TemplateBinding FontWeight}”
                         Foreground=”{TemplateBinding Foreground}”
                         HorizontalContentAlignment=”{TemplateBinding HorizontalContentAlignment}”
                         Padding=”{TemplateBinding Padding}”
                         TextAlignment=”{TemplateBinding TextAlignment}”
                         TextDecorations=”{TemplateBinding TextDecorations}”
                         TextWrapping=”{TemplateBinding TextWrapping}”
                         VerticalContentAlignment=”{TemplateBinding VerticalContentAlignment}”
                         Margin=”{TemplateBinding Margin}”
                         IsHitTestVisible=”true”
                         MinWidth=”{TemplateBinding MinWidth}”/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Application.Resources>

All I’ve done here is taken the default RadioButton style downloaded from here, removed the requisite ellipses and replaced them with Border controls. I’ve also adjusted the various state StoryBoards to target these Borders. The Borders are the familiar rounded tab shape surrounding the text and the StoryBoards define their mouseover, pressed and disabled states. RadioButtons are ideal for this purpose because they contain all the toggling functionality that a simple tab menu requires.

This is what it should look like:

tabstrip

Clicking on each tab will animate it to white and toggle the previously selected tab. Mousing over a tab turns it 50% white. I personally prefer tabs to be all the same width regardless of their text content. You can make each tab’s width match it’s text by setting each RadioButton’s MinWidth to 0 or just omitting MinWidth. It’s also worth noting that you don’t have to have tab backgrounds at all and can just use this as a handy way of creating horizontal lists of text-only buttons.

From here you could use the MainMenu_SelectionChanged event handler to show/hide corresponding Canvas controls when the tabs are toggled.

I may turn this into a more generic reusable TabMenu control in future but for now this is a pretty good way to get quick results.

Download the source code here

Centered Silverlight 2.0 Content

A very common layout for Flash sites is to center a rectangle of content horizontally and vertically in the browser window.

centered

I noticed that a method for doing this for Silverlight using css was posted here: http://michaelsync.net/2008/03/17/tipstricks-how-to-center-silverlight-control-on-a-webpage

This approach is good but I thought I’d suggest an alternative more in keeping with our particular way of working.

For Flash sites we tend to prefer to make the movie fill the entire window and then use actionscript to center the rectangle rather than css. We’ve found that the extra screen real-estate for Flash to redraw doesn’t significantly effect performance because of Flash’s “dirty rectangles” system. It’s also worth noting that the full-browser approach is a common practice for many Flex apps.

Here’s a simple way of getting this effect in Silverlight.

Set the width and height properties of your Silverlight control to 100%. Then in the root UserControl create a (scale 9) Grid like this:

<UserControl x:Class=”LayoutRoot”
xmlns=”http://schemas.microsoft.com/client/2007&#8243;    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”&gt;
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width=”*”/>
            <ColumnDefinition Width=”800″/>
            <ColumnDefinition Width=”*”/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height=”*”/>
            <RowDefinition Height=”600″/>
            <RowDefinition Height=”*”/>
        </Grid.RowDefinitions>      
       
<Canvas Grid.Column=”1″
           Grid.Row=”1″>
            <!– Content goes here –>
        </Canvas>
    </Grid>
</
UserControl>

Leave the root UserControl’s width and height properties blank so it stretches to fill the available space.

Update:

In order to get rid of the default margins of your page so the Silverlight control fills it completely you could use css like the following:

   
/* hide from ie on mac \*/
html {
   
height: 100%;
   
overflow: hidden;
    }

#SilverlightControlHost {
   
height: 100%;
   
width: 100%;
    }
/* end hide */

body {
   
height: 100%;
   
margin: 0;
   
padding: 0;
    }

This is the same as the css we use for Flash sites except the div wrapping the plugin has been renamed “SilverlightControlHost”.

Back to work

Well I’m back from Mix08 in Vegas and my subsequent Italian snowboarding holiday and now I’m spelunking Silverlight 2 in preparation for some client work.

Mix08 was an incredible event and I thoroughly enjoyed meeting new people as well as friends who were attending. There was so much going on and being announced that it wouldn’t do it justice to summarise here.

From what I’ve seen Silverlight is going through a phase similar to the early days of Flash where developers are sharing tips and tricks and trying to settle on standard patterns and practices. However it feels like this process is on steroids due perhaps to the number of blogging asp.net developers. I’m trying to filter all this information into my own implementation of a Cms-driven site which I’ll give code samples for in due course.

Here are some particularly helpful Silverlight blogs I’ve come across:

http://www.cameronalbert.com/Default.aspx
http://blogs.msdn.com/dancre/default.aspx
http://community.irritatedvowel.com/blogs/pete_browns_blog/default.aspx
http://silverlightrocks.com/community/blogs/silverlight_games_101/default.aspx
http://geekswithblogs.net/WynApseTechnicalMusings/Default.aspx

Routed Events

My intention for this blog was to write mainly about Silverlight as this is the most exciting technology for me being a .Net developer for a company that primarily makes RIA’s. Finally I’ll get to make the sexy front-end stuff again!  However after fiddling with Silverlight in its current form I quickly ran into a wall – the lack of Routed Events. This was a real showstopper for me as I want multiple listeners for single events like in Flash. This really stopped me in my tracks and I resolved to wait until Silverlight 2.0 came out and (hopefully) included this crucial functionality. There are solutions out there like this but my feeling about it is that I shouldn’t need to use a hack and this is symptomatic of the overall present alpha-ness of Silverlight. Better to wait until the platform is at least in Beta before committing a ton of time to learning it and bypassing its shortcomings. Until then I’ll continue to write speculative ruminations about technology :-)

I’m off to Mix08 in March which is all rather exciting. Sounds like we’re in for a huge amount of new stuff being released to coincide with Mix such as IIS7, Silverlight 2.0, Visual Studio 2008 etc. Should give me plenty to write about!

Something that’s been going around my head recently is why haven’t I heard about Blinq for Silverlight yet? Blinq is a system for generating Asp.Net web forms automatically to enable CRUD operations from a database schema. Linq (language Integrated Query) is the technology that enables this scenario. Silverlight 2.0 has Linq built in and will have form controls like text areas, drop down lists and datagrids. Surely it’s no biggy for someone to build a Blinq for Silverlight? Perhaps this will be announced at Mix. The prospect of having CRUD forms generated automatically then just needing to style them is a rather appealing one (at least to me).

The potential of desktop Linux + SAAS

This article (via Slashdot) sums up my theory regarding the importance of Silverlight at Microsoft much better than I could.

Desktop Linux plus RIA/SAAS equals a free, lightweight and reliable operating system with many applications running on it of roughly comparable quality to those currently available on Windows or OSX. However, for this to become more than a niche market it depends on three assumptions as far as I can tell.

One, high speed Internet access is on course for being ubiquitous and people are comfortable with their sensitive personal data being transmitted over the web. Recent reports about the explosion of Internet Christmas shopping would seem to bear this out at least for the UK.

Two, all major desktop apps will eventually be rewritten as RIA’s. We’ve already seen that key business apps like Office and Photoshop are in the works. Apps like 3D Studio Max may take a lot longer to emerge, but I wouldn’t say that the absence of 3D Studio Max is much of a deal-breaker for people happy to use a cheap and cheerful laptop for all their computing.

Three, people are willing to pay for software as a subscription or put up with advertisements being in their face all day. In my opinion it won’t be long until we hear about people with a high tolerance for sponsored messages doing all their computing completely for free. Just browsing the web or using Google already exposes us to a lot of this, so it probably won’t be much of a leap.

Personally I look forward to a day when all operating systems are as lightweight as possible and only exist to provide the necessary substrate for runtimes like Flash, Silverlight or JavaFX. Microsoft’s Singularity project could be worth watching in this respect. Perhaps Web Development agencies will end up dropping the “Web” from their professional designation?

Hello world

Not sure if this is a good idea or not, but I seem to remember that I enjoyed writing once so I’ll see if I can re-capture that. That’s a whole topic right there to talk about, why would I no longer enjoy writing? Is it because I spend my whole day writing emails that started off as being well-crafted and have gradually degenerated into time-saving bluntness? Has this created an association in my brain between writing my thoughts down and wasting time? I suppose I could start formulating a clich√©d argument here that email, text-messaging, social networks and whatever other predominant technologies are slowly eroding our collective capacity for creative writing. Nah. New forms of communication can only be good, it’s when people don’t communicate that you get problems, isn’t it? Saying that though, I could do without those inane comments you get on youtube… Perhaps www.stupidfilter.org is the answer? Now, I don’t wish to presume anything about my reader, but don’t you sometimes wish you had a stupid-filter for yourself? I certainly do. It could bleep me whenever I say something in order to fill an uncomfortable silence, or even temporarily blind people with a flash of light as I spill a drink all over myself. Hmm, I am enjoying writing¬†this. Yay!

Follow

Get every new post delivered to your Inbox.