Jeff Blankenburg is a passionate technologist with a wide range of interests.
This website is dedicated to discussing the ideas that pass through his head.

The main header for this website was created using Microsoft Silverlight.
Install it to see what you're missing!

Get Silverlight to see the whole site!

Day #4: Communicating Between Two Silverlight Controls

Saturday, July 04, 2009

Have you ever wondered how to get more than one Silverlight element on your page? Have you ever wondered how to get two Silverlight controls to communicate? This post will address both of those questions.

For those of you not pondering those questions, here's a common scenario: You want to have a common Silverlight navigation on your page, and you don't want to redirect the user to another page for each click. Instead, we want a second Silverlight element on the page that changes as we click the nav.

It's generally bad user experience to put everything in one, giant Silverlight container, because it will take FOREVER to load, forcing your users to sit and wait before they can do anything. By being more modular, we improve load times, and it's actually pretty simple to do. Let's get started:

1. Create your Silverlight project.




Make sure you create your accompanying Web project as well..



2. Make this XAML unique.

I'm just going to make the background of the Silverlight app orange. I've also added a "1" so that I'm sure which control it is. When we put 2 Silverlight controls on a page, we want to make sure we know which is which. There are also three buttons on this screen. When the user clicks those buttons, we're going to change the background color of the other Silverlight control. We'll get to the event handler code a little later. (You might also need to add the System.Windows.Browser namespace...it's for talking to the DOM). Here's the XAML I am using:

<UserControl x:Class="SilverlightWithTwoControls.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<
StackPanel x:Name="LayoutRoot" Background="Orange" HorizontalAlignment="Center" VerticalAlignment="Center" Width="400" Height="300">
<
TextBlock Text="1" FontSize="100"></TextBlock>
<
Button x:Name="Green" Content="Green" Width="100" Height="25" Margin="10" Click="Button_Click" />
<
Button x:Name="Purple" Content="Purple" Width="100" Height="25" Margin="10" Click="Button_Click" />
<
Button x:Name="Blue" Content="Blue" Width="100" Height="25" Margin="10" Click="Button_Click" />
</
StackPanel>
</
UserControl>


3. Create another Silverlight project.

Each Silverlight project will be independent of each other. Each Silverlight project creates ONE XAP file, and since we need two, this is the best solution.



4. Mark up our second XAML file.

This file is even simpler. We're only modifying the background color and adding a 2 for identification. Here's the code:

<UserControl x:Class="SecondControl.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="#666666" HorizontalAlignment="Center" VerticalAlignment="Center" Width="400" Height="300">
<
TextBlock Text="2" FontSize="100"></TextBlock>
</
Canvas>
</
UserControl>


5. Let's add these to our .aspx page.

We're just going to have 2 <asp:Silverlight> tags on our page in this example, pointing to the two individual .xap files. Here's what the HTML looks like:

<%@ Page Language="C#" AutoEventWireup="true" %>
<%
@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<
html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;">
<
head runat="server">
<
title>Silverlight With Two Controls</title>
</
head>
<
body style="height:100%;margin:0;">
<
form id="form1" runat="server" style="height:100%;">
<
asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<
div style="position:absolute;top:10px;left:10px;">
<
asp:Silverlight ID="Xaml1" runat="server" Source="/ClientBin/SilverlightWithTwoControls.xap" MinimumVersion="2.0.31005.0" Width="400" Height="300" />
</
div>
<
div style="position:absolute;top:320px;left:10px;">
<
asp:Silverlight ID="Xaml2" runat="server" Source="/ClientBin/SecondControl.xap" MinimumVersion="2.0.31005.0" Width="400" Height="300" />
</
div>
</
form>
</
body>
</
html>


6. Writing the button event handler.

We need those buttons to actually do something. Let's write that event handler code. Here's what it looks like:

private void Button_Click(object sender, RoutedEventArgs e)
{
Button clicky = sender as Button;
HtmlPage.Window.Invoke("changeColor", clicky.Name);
}


7. Say it ain't so...

I don't know how many times I can tell you that Javascript rules the world, but here's another example. We're going to leverage the power of Javascript to talk between our Silverlight objects. Because it has the ability to leverage the Silverlight DOM, it's actually a very useful and powerful tool. (And for all of you naysayers, if a user has Javascript turned off, it's HIGHLY likely they're not running rich UI plugins like Silverlight or Flash either.)

Anyways, there's a pretty simple Javascript function we can write to get this action taken care of. In our previous step, we specified the name of the Javascript function, changeColors. We also pass the Name value of the Button, which just happens to be the name of the color we're going to be changing the other control to. Forethought is cool. Here's what my Javascript function looks like:

function changeColor(color) {
slObject = document.getElementById("Xaml2");
slObject.Content.Page.ChangeBackgroundColor(color);
}


What we've done here is call the method ChangeBackgroundColor inside the Xaml2 control. We're passing the color we want to change it to.

8. Writing the final method in the 2nd control.

Now we just need to write that method in the code-behind of our second XAML file, and we should be done. Here's my final code for the second control:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;

namespace SecondControl
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
}

[ScriptableMember]
public void ChangeBackgroundColor(string colorName)
{
if (colorName == "Blue")
{
LayoutRoot.Background = new SolidColorBrush(Colors.Blue);
}
else if (colorName == "Purple")
{
LayoutRoot.Background = new SolidColorBrush(Colors.Purple);
}
else if (colorName == "Green")
{
LayoutRoot.Background = new SolidColorBrush(Colors.Green);
}
}
}
}


You might have noticed that there's something a little different in there. We have a decorator [ScriptableMember] in there. We had to make some changes to our application to make it exposed to Javascript. By default, it can't just call inside our Silverlight app. We have to make that happen in code.

9. Editing our App.xaml file.

In the second Silverlight project, open your app.xaml file. In our Application_Startup method, you should have a line that looks like
this.RootVisual = new Page();
. We're going to add one more line after that, which registers our control as a Scriptable object. Here's the entire method, after my modifications:

private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new Page();
HtmlPage.RegisterScriptableObject("Page", this.RootVisual);
}


This line of code, in conjunction with the decorator we added in Step #8 will mean we're done, and that our controls can now affect each other.

Sample Code

You can download the sample code for this example here. You should also be able to see these controls below this paragraph, but RSS readers like to ignore it. If it's not showing up, you can also see Two Silverlight Controls together by clicking here.










Get Microsoft Silverlight












Get Microsoft Silverlight

Labels: , ,

posted by Jeff Blankenburg, 1:00 AM | link | 0 comments |

Day #3: Custom Silverlight Loading Screen

Friday, July 03, 2009

This is the third post in my series of thirty-one, called, not surprisingly, "31 Days of Silverlight". You can find the master list here.

Also, before we get started here, don't forget that today is Contribupendence Day. Take a moment to read this post about what Contribupedence Day is, and how you can participate.

If you've ever seen a Silverlight application before, you've likely seen the default loading screen. Here's a example of what I'm talking about:



Now, there's nothing wrong with it, except that it's the thing you see EVERYWHERE. There's a way to customize this screen, and you should. It's an opportunity to re-inforce your branding, entertain your user, and differentiate yourself from everyone else. Let's get started.

Building Our Loading Screen

The first thing to know about this loading screen is that it functions completely outside of our .xap file. If you think about it though, it makes sense. We're trying to monitor the loading percentage of our XAP file, so we could hardly expect our loading code to be inside it, right?

So, instead of creating a new XAML file inside of our Silverlight project, we're going to create a XAML file inside our Web Project this time. When you choose "Add > New Item...", you're going to choose the "Silverlight JScript File." This will create a XAML file in our web project, but otherwise, it's your standard XAML. I've created one that has a TextBlock to display the percentage as a number, as well as a rectangle underneath. This rectangle will be my percentage progress bar. Here's the code (I named it LoadingScreen.xaml):

<Canvas xmlns="http://schemas.microsoft.com/client/2007" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300">
<
Canvas x:Name="LayoutRoot" Background="#FFB5EFFF">
<
Rectangle Height="4" Width="0" Fill="#FFE8B03A" Stroke="#FF999999" StrokeThickness="1" x:Name="ProgressBar" Canvas.Left="14" Canvas.Top="156"/>
<
TextBlock Width="100" FontFamily="ROCK.TTF#Rockwell" FontSize="48" Text="Blankenthoughts" Foreground="#FF6D6D6D" x:Name="Title" Canvas.Top="56" Canvas.Left="150" />
</
Canvas>
</
Canvas>


Getting Our Loading Screen Loaded

So we've got a loading screen now, but we also need to make sure that our Silverlight <object> tag knows that we've got a custom loading screen. We do this with a param tag in the HTML. The splashscreensource tag specifies a XAML file that should be used instead of the default. Here's how my entire HTML file looks now:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<
html xmlns="http://www.w3.org/1999/xhtml" >
<
head>
<
title>SilverlightLoadingScreen</title>
</
head>

<
body>
<
div id="silverlightControlHost">
<
object id="xamlobject" data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<
param name="splashscreensource" value="LoadingScreen.xaml"/>
<
param name="source" value="ClientBin/SilverlightLoadingScreen.xap"/>
<
param name="background" value="white" />
</
object>
</
div>
</
body>
</
html>


What you may notice, if you're building along with me, is that the loading screen loads, but it doesn't change as the load progresses. This is because we need to pay attention to the "onSourceDownloadProgressChanged" event. Thankfully, we do with with another param tag in our <object> tag. The value that we provide is actually the name of the Javascript function we will write. That tag looks like this:

<param name="onSourceDownloadProgressChanged" value="onSourceDownloadProgressChanged" />


You didn't tell me there'd be Javascript

Ah, never doubt for a second that the Internet runs on Javascript. Of course it does! This function is simple, and is the glue that puts our XAML together with actual data. I'll give you my function first, and then we can discuss the different parts of it.

function onSourceDownloadProgressChanged(sender, eventArgs)
{
var slObject = document.getElementById("xamlobject");
var progressBar = slObject.content.findName("ProgressBar");
var progressTitle = slObject.content.findName("Title");
if (eventArgs.progress)
{
progressBar.Width = eventArgs.progress * 370;
progressTitle.Text = parseInt(eventArgs.progress * 100) + "%";
}
else
{
progressBar.Width = eventArgs.get_progress() * 370;
progressTitle.Text = parseInt(eventArgs.get_progress() * 100) + "%";
}
}


  • slObject - this is a reference to my Silverlight <object> tag on the page. I need to get this in order to find the child elements, specifically my Rectangle and TextBlock elements.
  • progressBar - this is a reference to my ProgressBar Rectangle element within my XAML document. Don't you wish getting through XML was always that easy? It just searches through the document tree until it finds an element with the name I specified.
  • progressTitle - a TextBlock in the XAML that will hold the actual percentage of completion.
  • eventArgs.progress - this is the physical number that represents our completion percentage. We use this to modify the width of our rectangle, so that it grows as the percentage increases. I am also displaying this number in the TextBlock, appending a "%" to the end.
  • eventArgs.get_progress()
  • - basically, we need to call the get_progress method in case our page is not already paying attention to it. Once this has been called, however, it will default to the previous part of the if statement, using just the progress property of the eventArgs.


Can I See A Working Example?

Absolutely. Below is a working example of this custom loading screen in action. If you don't see it, you're probably reading this post from an RSS reader. Click here to see the Silverlight Loading Screen as a working example. You can also click here to download my entire set of working code.












Get Microsoft Silverlight

Labels: , ,

posted by Jeff Blankenburg, 1:00 AM | link | 2 comments |

Day #2: Silverlight Screen Transitions

Thursday, July 02, 2009

This is second of thirty-one posts on Silverlight I will be doing in July. The first post was on the mouse events available to you in Silverlight. Today's post is on Screen Transitions, or more specifically, moving from one XAML file to another.

Moving From One XAML File To Another

This is the simple part. In your Silverlight project (mine is called SilverlightScreenTransitions), add a new XAML file. You can do this by right clicking on the project name, and choosing "Add > New Item." You won't see "XAML File" as one of the choices, because each XAML file in Silverlight is considered a User Control. So choose "Silverlight User Control," and give it a meaningful name, like page2.xaml. :)

Now jump back into your default XAML file, Page.xaml. We need a button, or a link, or something that will allow us to navigation to our new page. Here's the new XAML for our default page:

<UserControl x:Class="SilverlightScreenTransitions.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="White">
<
Rectangle x:Name="Clicky" Width="200" Height="50" Fill="Red" Canvas.Top="125" Canvas.Left="100" Stroke="Black" StrokeThickness="4" MouseLeftButtonUp="Clicky_MouseLeftButtonUp"/>
</
Canvas>
</
UserControl>


All this does is put a red rectangle in the middle of our control. Next, we're going to need to edit our second page. We'll just put a "Congratulations!" textbox on the page, so we know we made it. Here's the XAML for Page2.xaml:

<UserControl x:Class="SilverlightScreenTransitions.Page2"
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="White">
<
TextBlock Width="200" Height="50" Canvas.Top="125" Canvas.Left="100" Text="Congratulations!" TextAlignment="Center" FontSize="25"/>
</
Canvas>
</
UserControl>


The magic line of code

At this point, we have two XAML files, one with a rectangle (with an event handler), and the other with just a TextBlock. When we click on the Rectangle, we want to go to the other XAML file. Here's how you do it (in VB.NET, just ignore the semi-colon). Just add this line to your event handler code in Page.xaml.cs (or .vb):

this.Content = new Page2();


I thought this post was about transitions...

Oh, patience, my friends. Now that we know how to get from one screen to another, we can talk about transitions. Let me first start by defining transition:

The animated movement from one XAML file to another. Think transitions in Powerpoint. Fades, Dissolves, etc. We'll create an example of that in this post.

Fading In and Out

We're going to create a fading transition from the first slide to the second. What I'm going to do is create an animation in each XAML file. In Page.xaml, we'll create an animation that fades out. In Page2.xaml, we'll create an animation that fades it in. Between the two, we'll jump from one file to the next, using the code we wrote earlier.

Page.xaml animation

The only difference is the new Storyboard I created. It just takes the opacity of the LayoutRoot element from 100% to 0% in one second:

<UserControl x:Class="SilverlightScreenTransitions.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<
UserControl.Resources>
<
Storyboard x:Name="FadeOut">
<
DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Opacity)">
<
SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
<
SplineDoubleKeyFrame KeyTime="00:00:01" Value="0"/>
</
DoubleAnimationUsingKeyFrames>
</
Storyboard>
</
UserControl.Resources>
<
Canvas x:Name="LayoutRoot" Background="White" Opacity="1">
<
Rectangle x:Name="Clicky" Width="200" Height="50" Fill="Red" Canvas.Top="125" Canvas.Left="100" Stroke="Black" StrokeThickness="4" MouseLeftButtonUp="Clicky_MouseLeftButtonUp"/>
</
Canvas>
</
UserControl>


Page2.xaml animation

We are doing the exact opposite animation for this file, but there's one other thing to consider in this case. Even though our animation takes the opacity from 0% to 100%, we need to make sure that the initial opacity of our LayoutRoot element is set to 0%. Without that, the XAML file will load with it at 100%, and then the animation will kick off, fading it from 0 to 100. Not exactly the desired effect. So you'll see the opacity specified in the LayoutRoot element as well.

<UserControl x:Class="SilverlightScreenTransitions.Page2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<
UserControl.Resources>
<
Storyboard x:Name="FadeIn">
<
DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Opacity)">
<
SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<
SplineDoubleKeyFrame KeyTime="00:00:01" Value="1"/>
</
DoubleAnimationUsingKeyFrames>
</
Storyboard>
</
UserControl.Resources>
<
Canvas x:Name="LayoutRoot" Background="White" Opacity="0">
<
TextBlock Width="200" Height="50" Canvas.Top="125" Canvas.Left="100" Text="Congratulations!" TextAlignment="Center" FontSize="25"/>
</
Canvas>
</
UserControl>


An Animation Event Handler?

So we obviously also need to change our code-behind, so that when we click, we call the animation. But how do we know when the animation is done? Well, we know it's going to take exactly ONE second, so technically, we could create a timer, wait 1 second, and then make the call to the second XAML file. But that's messy, and depending on ANY sort of lag, would be inaccurate. Thankfully, we have the ability to add event handlers to our animations as well. So, we can create a "Completed" event handler on our FadeOut animation, which will get called immediately after the animation completes. No guess work. Here's our new code-behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightScreenTransitions
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
FadeOut.Completed += new EventHandler(FadeOut_Completed);
}

void FadeOut_Completed(object sender, EventArgs e)
{
this.Content = new Page2();
}

private void Clicky_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
FadeOut.Begin();
}
}
}


Catching the animation on the other side

Transitioning into the next XAML file is simple, in the initial method, we call the FadeOut animation we created.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightScreenTransitions
{
public partial class Page2 : UserControl
{
public Page2()
{
InitializeComponent();
FadeIn.Begin();
}
}
}


The final working example

Below is the Silverlight application, up and running. If you're viewing this in an RSS reader, it may not show up, but you can click here to see the Silverlight Screen Transition working. You can also download all of the source code for this project here.







Get Microsoft Silverlight

Labels: , ,

posted by Jeff Blankenburg, 1:00 AM | link | 3 comments |

Day #1: Mouse Events in Silverlight

Wednesday, July 01, 2009

In my inaugural post of the "31 Days of Silverlight," we're going to focus on Mouse Event handlers. With an interactive application, you're often going to want to know when your users are clicking on stuff. So, this is a tutorial on the different mouse events, and how to use them. So, let's start with the beginning, and go forward from there. You can download ALL of the sample code from this post here.

MouseEnter

I am going to demonstrate this on two levels. The first will be a MouseEnter event on the Silverlight control as a whole. This event will fire when the user's mouse enters the space that the Silverlight control takes up. We will be putting a second event on a circle that is in the Silverlight application. Here's our starter XAML.

<UserControl x:Class="SilverlightMouseEvents.MouseEnterDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<
Grid x:Name="LayoutRoot" Background="White">
<
Ellipse x:Name="myEllipse" Fill="Blue" Width="150" Height="150" />
</
Grid>
</
UserControl>


I am going to add the event handlers to the XAML, but I will show you how to do it in code as well. Here's our modified XAML, with the event handlers inline.
<UserControl x:Class="SilverlightMouseEvents.MouseEnterDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300" MouseEnter="UserControl_MouseEnter">
<
Grid x:Name="LayoutRoot" Background="White">
<
Ellipse x:Name="myEllipse" Fill="Blue" Width="150" Height="150" MouseEnter="myEllipse_MouseEnter" />
</
Grid>
</
UserControl>

Now we need to jump into the code-behind to write the event handler actions. As soon as I created the event handlers in the XAML, it automatically stubbed out the methods for me in code. Here's how my initial C# code-behind looks.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseEnterDemo : UserControl
{
public MouseEnterDemo()
{
InitializeComponent();
}

private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{

}

private void myEllipse_MouseEnter(object sender, MouseEventArgs e)
{

}
}
}

In order to keep this post reasonable in length, I'm not going to do anything complicated in my event handling, but I will show you how to change the color of the Ellipse. I've added one line of code to each method, and each one changes the Ellipse to a different color. At this point, when we run our mouse into the Silverlight area of our web page, the circle will change to green, and when we mouse over the circle, it turns purple.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseEnterDemo : UserControl
{
public MouseEnterDemo()
{
InitializeComponent();
}

private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{
myEllipse.Fill = new SolidColorBrush(Colors.Green);
}

private void myEllipse_MouseEnter(object sender, MouseEventArgs e)
{
myEllipse.Fill = new SolidColorBrush(Colors.Purple);
}
}
}


MouseLeave

In this case, it's pretty much exactly the same as MouseEnter, but when the mouse LEAVES something. Novel idea, huh? This time, however, I will not have any modifications to my XAML at all. So here's the starter XAML again.

<UserControl x:Class="SilverlightMouseEvents.MouseLeaveDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<
Grid x:Name="LayoutRoot" Background="White">
<
Ellipse x:Name="myEllipse" Fill="Blue" Width="150" Height="150" />
</
Grid>
</
UserControl>


This time I am going to do this all in the code-behind. I will add the event handlers when the application initializes. Here's my final C# for this example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseLeaveDemo : UserControl
{
public MouseLeaveDemo()
{
InitializeComponent();
this.MouseLeave += new MouseEventHandler(MouseLeaveDemo_MouseLeave);
myEllipse.MouseLeave += new MouseEventHandler(myEllipse_MouseLeave);
}

void myEllipse_MouseLeave(object sender, MouseEventArgs e)
{
myEllipse.Fill = new SolidColorBrush(Colors.Purple);
}

void MouseLeaveDemo_MouseLeave(object sender, MouseEventArgs e)
{
myEllipse.Fill = new SolidColorBrush(Colors.Green);
}
}
}


MouseLeftButtonDown

For this event, I am going to continue to use the same XAML over and over. The only thing that changes is the reference to the class our XAML user control is using. I've shown how to rig up event handlers both in the XAML as well as in code. So, you've seen the XAML, I'm going to just show the code-behind for the next example here.

MouseLeftButtonDown is exactly like it looks. It fires when the user's left mouse button is pressed. Please note that I will be covering MouseLeftButtonUp next, and that there's a significant distinction between them. It's especially apparent when you start implementing Drag & Drop. Here's an example of adding MouseLeftButtonDown to our code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseLeftButtonDownDemo : UserControl
{
public MouseLeftButtonDownDemo()
{
InitializeComponent();
this.MouseLeftButtonDown += new MouseButtonEventHandler(MouseLeftButtonDownDemo_MouseLeftButtonDown);
myEllipse.MouseLeftButtonDown += new MouseButtonEventHandler(myEllipse_MouseLeftButtonDown);
}

void myEllipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
myEllipse.Fill = new SolidColorBrush(Colors.Green);
}

void MouseLeftButtonDownDemo_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
LayoutRoot.Background = new SolidColorBrush(Colors.Purple);
}
}
}


MouseLeftButtonUp

So far, we've created an event handler method for each individual event. There are many cases, however, where you want multiple items to be able to call the same method, so you're not writing the same code over and over. In this next example, I'm going to add a second circle, and have both of them change the background of the StackPanel they sit inside. Here's our new XAML file.

<UserControl x:Class="SilverlightMouseEvents.MouseLeftButtonUpDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<
StackPanel x:Name="LayoutRoot" Background="White" Orientation="Horizontal" HorizontalAlignment="Center" >
<
Ellipse x:Name="myEllipse" Fill="Blue" Width="150" Height="150" />
<
Ellipse x:Name="myEllipse" Fill="Red" Width="150" Height="150" />
</
StackPanel>
</
UserControl>


Now, we want each of the Ellipses, when the MouseLeftButtonUp event fires on them, to change the background of the ellipse that fired. Here's what the code looks like to do that.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseLeftButtonUpDemo : UserControl
{
public MouseLeftButtonUpDemo()
{
InitializeComponent();
myEllipse.MouseLeftButtonUp += new MouseButtonEventHandler(Ellipse_MouseLeftButtonUp);
myEllipse2.MouseLeftButtonUp += new MouseButtonEventHandler(Ellipse_MouseLeftButtonUp);
}

void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Ellipse myCircle = sender as Ellipse;
myCircle.Fill = new SolidColorBrush(Colors.Orange);
}
}
}


You'll notice with this example that there's a second line of code in our event handler method. We have to grab a reference to the Ellipse that actually called the method. The "sender" parameter contains this information, so we have to grab that reference before assigning our new color.

MouseMove

In this final example, we are going to use the MouseMove event. Each time the mouse moves from its previous location, this event will fire. You can assign this to the entire control, or just a specific element of the application. In either case, you can do quite a few things with this, including drag and drop. We will cover that in a future post.

My XAML this time has two TextBoxes on the page. One named (cleverly) Xbox, and the other Ybox. We're going to insert the mouse's X and Y coordinates in these boxes as the user moves their mouse.

<UserControl x:Class="SilverlightMouseEvents.MouseMoveDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300" VerticalAlignment="Center">
<
StackPanel x:Name="LayoutRoot" Background="White">
<
TextBox x:Name="Xbox" Width="200" Height="35" Text="X" />
<
TextBox x:Name="Ybox" Width="200" Height="35" Text="Y"/>
</
StackPanel>
</
UserControl>


The code behind this probably doesn't look too complicated now, if you've followed this entire post, but we're using the MouseEventArgs this time, to determine where the mouse's current position is. We then simply assign those values to the text boxes.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightMouseEvents
{
public partial class MouseMoveDemo : UserControl
{
public MouseMoveDemo()
{
InitializeComponent();
this.MouseMove += new MouseEventHandler(MouseMoveDemo_MouseMove);
}

void MouseMoveDemo_MouseMove(object sender, MouseEventArgs e)
{
Xbox.Text = e.GetPosition(null).X.ToString();
Ybox.Text = e.GetPosition(null).Y.ToString();
}
}
}


Summary

This was a quick overview of the Mouse events that are available to you in Silverlight. Used together, you can create a pretty interactive environment for your user to use. In tomorrow's post, we are going to be covering screen transitions. Not only the ability to jump from one XAML file to the next, but also how to incorporate some Powerpoint-like transitions from one screen to the next.

kick it on DotNetKicks.com

Labels: , ,

posted by Jeff Blankenburg, 1:00 AM | link | 0 comments |

Thirty-One Days of Silverlight

Tuesday, June 30, 2009

Each day in the month of July, I am going to publish an article on a Silverlight topic. The topics will range from 100-level to 300-level in difficulty, but all of them will be written so that a beginner could start from scratch to create them.

I will covering Drag & Drop, Event Handling, and even Collision Detection. This is an extensive list of tutorials, and I hope that it will help you see how useful and powerful these technologies can be.

If there are topics you are specifically interested in seeing covered, please leave a comment, and I will do my best to accomodate your request. Below is a list of the articles that have been published.

Day #1: Mouse Events in Silverlight

Day #2: Silverlight Screen Transitions

Labels: ,

posted by Jeff Blankenburg, 1:00 AM | link | 10 comments |

TUTORIAL: How To Create A SetTimeout Function In Silverlight

Monday, June 15, 2009

I am in the process of creating my first game in Silverlight, and one of the first things that I noticed I was missing from my Javascript-era toolkit was the setTimeout() function.

In short, this little function is the be-all, end-all of Javascript animation. It is the device you use to insert little "pauses" into your code so that objects appear to be moving. Without it, your pieces would simply start at one position, and appear at the final destination. I use it primarily to make sure that the browser takes the time to draw each step of the animation. Here's an example of me using the setTimeout() function in Javascript, circa 1999 (it's also less than 5K in total size!):



1. Create a new UIToolkit Class.

It was tempting when starting this tutorial to just create a class that does one thing. But as I move forward in my Silverlight adventures, it occurs to me that we're probably going to encounter more of these types of needs in the future. So, I'm creating a UIToolkit class in my project. This will contain all of the little helper functions I create going forwards.

public static class UIHelper
{

}

2. Inherit from System.Windows.Threading.DispatcherTimer

We are primarily going to be using the DispatcherTimer as is, but we also need it to accept an Action to execute when the timer expires. So we will be creating a new class that inherits from the standard DispatcherTimer, adding an Action to its definition.

public class ActionTimer: System.Windows.Threading.DispatcherTimer
{
public Action Action { get; set; }
}


3. Create a setTimeout method in UIToolkit

To keep it familiar for the Javascript folks out there, I'm keeping the name of the method setTimeout. It's not even my usual casing, but for this example, I'm going to stick with the Javascript syntax.

Inside this method, we're going to need an instance of our new ActionTimer, including the interval we want, and the method to call, as well as the calls to kick off the timer, and an event handler to manage each tick of the timer. Here's the code:

public static void setTimeout(int milliseconds, Action action)
{
var timer = new ActionTimer
{
Interval = new TimeSpan(0, 0, 0, 0, milliseconds),
Action = action
};
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}

static void timer_Tick(object sender, EventArgs e)
{
var t = sender as ActionTimer;
t.Stop();
t.Action();
t.Tick -= timer_Tick;
}


Or, just copy this into a new class file


public static class UIToolkit
{
public static void setTimeout(int milliseconds, Action action)
{
var timer = new ActionTimer
{
Interval = new TimeSpan(0, 0, 0, 0, milliseconds),
Action = action
};
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}

static void timer_Tick(object sender, EventArgs e)
{
var t = sender as ActionTimer;
t.Stop();
t.Action();
t.Tick -= timer_Tick;
}
}

public class ActionTimer : System.Windows.Threading.DispatcherTimer
{
public Action Action { get; set; }
}


4. How to call our new method

Now that we've got a setTimeout method that takes a number of milliseconds and an action, we need to call it for testing purposes. Below is the syntax we'll be using. The major difference you'll notice between this and the Javascript implementation is that our new method will take an entire block of code as our Action. In Javascript, we're forced to concatenate a string of commands together, and it can get pretty messy fast. We are setting this up to call our method every 1000 milliseconds, or every ONE second.

UIToolkit.setTimeout(1000, () =>
{
OurRecurringMethodCallShouldGoHere();
});


Let's see it in action!

Click here if the Silverlight below doesn't load. Click here to download this sample code.







Get Microsoft Silverlight



kick it on DotNetKicks.com

Labels: , , ,

posted by Jeff Blankenburg, 8:50 PM | link | 0 comments |

Stir Trek (no, that's not a typo)

Thursday, March 26, 2009

Did you go to Mix '09? Neither did a lot of people. Don't get me wrong...it was well-attended, but in these tough times, it's getting harder and harder to justify the flights, hotels, meals, and conference fees for the major conferences anymore. So I'm doing my best to help you out.

On May 8th, we will be holding an event called Stir Trek. In short, it is meant to bring the highlights of the Mix conference to a location you can afford to visit. It will be held in Columbus, Ohio at the Marcus Crosswoods movie theater. But there's a twist.

There will be 10 sessions in two tracks, and they will run from 9am - 3pm. At 3pm, we're going to turn off the laptops and cell phones, and lean back to enjoy a private screening of the new Star Trek movie that is opening that day. It should be an amazing day.

We will be covering Silverlight 3, Internet Explorer 8, Expression Blend 3, User Experience Design, WPF, Rapid Prototyping with SketchFlow, and ASP.NET MVC, among other topics from the Mix 09 conference. In addition, Tim Heuer has agreed to join us for the day, and will be presenting the Silverlight 3 session. This will be a great opportunity for you to have direct access to a Silverlight expert from Microsoft for the day. Bring your questions, and be sure to ask them. Tim is a great developer and speaker, and I think he'll definitely add to what is already going to be a spectacular event.

We have put together a website for this event, and you can find it here: http://www.stirtrek.com. On the site, you'll find the most updated information available about the conference, including sessions, speakers, location, sponsors, etc.

I hope you'll join us for a full day of technology. I promise there will be NO jokes about developing for "The Enterprise."

kick it on DotNetKicks.com

Labels: , , , , , , ,

posted by Jeff Blankenburg, 9:30 PM | link | 5 comments |

10 Things I Want From The Next Windows Phone OS

Tuesday, February 10, 2009

In a day where Windows Mobile isn't the cool kid anymore, there's an opportunity to start thinking about how you would change things up. Let's start from the ground up, considering everything fair game for improvement or replacement.

There is much that can be asked for in a mobile phone these days, but I have put together a list of features that I would like to see on the next Windows Phone.

1) Speed. This device has to be fast. Fast to start programs. Fast to surf the web. Fast to get a GPS signal. I want the most responsive phone ever. I don't want to have to sit through "Spinning Simon." (If you have a Windows Mobile phone, you know what I'm talking about.)

2) Multi-touch This is, without question, one of the coolest features of the iPhone, and a new standard in feature-set requirements for a phone. It HAS to have this. (I'm actually surprised Android doesn't.)

3) Intuitive Silverlight interface I'd really like to see us leverage Silverlight technology for the OS. Not only would it help SL to gain prominence, but it also lends a world of application interface possibilities. Menus are a thing of the past. Let's get creative AND functional.

4) Design Nearly every device Microsoft has released has been criticized of being "ugly." Think of the first Xbox, or the first Zune. I think that a phone has to be stylish AND functional to succeed in today's market. Nobody wants to carry an ugly device. It's as much an accessory as a belt or shoes anymore.

5) Voice-recognition and speech-to-text For EVERYTHING. Give me the ability to use my phone, and every feature of it, without touching it. Make it a native part of the OS. Let it read me emails while I drive. Let it take dictation for an email while I'm playing video games.

6) Openness and extensibility This is one of the biggest weaknesses of the iPhone, in my opinion. It is a very closed OS, with plenty of hurdles to climb in order to get your applications available to the public. If someone creates a Flash plugin for the device, so be it. Why should we limit what someone can do with their device? Let's empower, not handicap people. Apps written by competitors like Apple, Adobe, and Google should run as well as an app written by Microsoft.

7) Technologically advanced Why are we still making phones with a 1 megapixel camera? The HTC HD has a 5MP camera, with auto-focus. And it's thin! Bluetooth, Wi-Fi, 80+ GB hard drive, MicroSD slot, mini-USB charger, strong battery life, GPS, and speakerphone. Don't be proprietary for ANYTHING. Let me use any charger, any accessory.

8) DRM compatibility Why isn't DRM transportable? Why can't I play my songs from iTunes on a Windows phone? Why can't I play songs from the Zune marketplace on an iPod? Let's find a way to authenticate any device against some DRM web services, and let me play my music anywhere. At the very least, let me play songs I bought from Microsoft (Zune marketplace) on my phone running a Microsoft OS (Windows Mobile).

9) Social interaction Make the phone capable of location-awareness. Let me find other users in my vicinity, and interact with them through games, apps, and messaging. Let me find my friends, and let my friends find me.

10) No device generation gaps Like the Zune, I want to know that when new software features are released for these devices, my v1 device will also receive those benefits. There should never be an older, less functional device. Build it with the hardware it will need, and then just start piling on the software to make it shine.

Labels: , , ,

posted by Jeff Blankenburg, 7:15 PM | link | 11 comments |

MDC = Mighty Darn Cool (great video enclosed)

Friday, January 16, 2009

I've been talking about MDC at user groups, Codemash, and plenty of other places, but it's time I talk about it here too.

The MSDN Developer Conference is coming to Detroit, MI on January 22. Yes. Next Thursday. How have you not registered for this yet?

PDC content, in your backyard, for 99 dollars? I'm disappointed in you. Seriously. You will walk out of this full day event, not only with a DVD copy of Windows 7 Beta, but with knowledge and information that you can be using TODAY on your software projects.

Andy Erickson recently attended the MDC event in Atlanta, and took his video camera with him. Take the time to watch this video. Is should be all of the convincing you need.

Labels: , , ,

posted by Jeff Blankenburg, 4:41 PM | link | 1 comments |

TUTORIAL #11: Creating a Navigation In Silverlight

Thursday, January 15, 2009

A navigation is always a tricky project for every application. It seems to be in a constant state of flux, up until the minute the site goes live. With Silverlight, some of that becomes easier. This post will show you how to create a simple navigation in Silverlight.

Before I start through the steps, I want to point out that the navigation on my site is actually the ONLY part of my site done in Silverlight. The rest of the page is standard ASP.NET. I don't recommend creating your entire site in Silverlight, but rather, using it where it's appropriate: like a navigation. OK, having said that, here we go.

1. Create a new project in Visual Studio.

For many of you, this may seem remedial, but I want to make sure that I am documenting all of my steps. There's something frustrating to me about tutorials that assume you know the first few steps.

Create a new project in Visual Studio.

2. Add the web project it asks you about.

After you create a Silverlight project, Visual Studio will prompt you to create a Web Project to accompany it. Silverlight projects have to be hosted in a web page, so go ahead and create it.

Add the web project it asks you about.

3. Make your XAML document larger.

Open the Page.xaml file in your Silverlight project. By default, your UserControl tag is set to 400 x 300, though I don't know why that was the dimensions that were picked. IN our case, we're going to make our navigation 800 x 200. So your XAML should look like this now:

<UserControl x:Class="NavigationSample.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="800" Height="200">
<
Grid x:Name="LayoutRoot" Background="White">

</
Grid>
</
UserControl>

4. Open your solution in Expression Blend.

I would ALWAYS recommend using Expression Blend for any kind of Silverlight or WPF layout work, because you have the ability to drag and drop your shapes and colors. The next few steps will be shown in Blend.

The first thing I did was open my solution files in Blend.



5. Draw your navigation in Page.xaml.

I am going to be creating a nav similar to the one on my site at http://jeffblankenburg.com.



Before I create anything, I want to change the default Grid control to a Canvas. You can do this simply by changing the work "Grid" to the word "Canvas" in the XAML. Make sure to get the closing /Grid tag too. If you want to understand the differences, I have posts on Canvas, Grid, and StackPanel respectively.

Looking at it, the first thing I want to create is that silverish outer border. That's simply a rectangle with some rounded edges. I've also applied a gradient to it, so it looks a little metallic. Finally, I just made the StrokeThickness = 2. Here's how it looks in Blend (click to enlarge):



Also, here's how our entire XAML looks now:

<UserControl x:Class="NavigationSample.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="800" Height="200">
<
Canvas x:Name="LayoutRoot" Background="White">
<
Rectangle Width="780" Height="100" Stroke="#FF666666" RadiusY="15" RadiusX="15" StrokeThickness="2" Canvas.Top="50" Canvas.Left="11">
<
Rectangle.Fill>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#FFC4C4C4" Offset="1"/>
<
GradientStop Color="#FFFFFFFF" Offset="0"/>
</
LinearGradientBrush>
</
Rectangle.Fill>
</
Rectangle>
</
Canvas>
</
UserControl>

6. Create the background for the buttons.

There are probably many different ways to approach this problem, so we'll have to live with my simplified solution. Each button on the navigation is orange, with a subtle gradient. It was created the same way that we created the previous rectangle, so here's the XAML for it:

 <Rectangle Height="80" Width="760" RadiusY="7" RadiusX="7" StrokeThickness="2" Stroke="#FFB1B1B1" Canvas.Left="21" Canvas.Top="60">
<
Rectangle.Fill>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#FFF7D599" Offset="1"/>
<
GradientStop Color="#FFE8AF34"/>
</
LinearGradientBrush>
</
Rectangle.Fill>
</
Rectangle>
All we need to do is take that XAML, and place it immediately after the rectangle we've already got there. Here's what your design view should look like now:



7. Position your TextBlocks.

We've now reached the step for why I wanted to be using a Canvas as our outer container. We're going to position each of our text elements, and we're looking for pixel by pixel accuracy. The Canvas provides us that.

One of the other things you'll notice about my navigation is that I am not using one of the standard 8 fonts that come with Silverlight. Thankfully, I've written a post on embedding fonts in Silverlight as well. Make sure you read that if you want something different than Arial, Times New Roman, or Courier. If you use Comic Sans, call me so I can smack you. :)

Anyways, I have 6 navigation elements that I want to create. I am simply using TextBlock controls to show text...they're not actually going to do anything. They just have to look pretty. All I did was create the first one, copy it 5 times, and drag each one to their positions. You should notice that Blend provides some nice guides for alignment purposes. It makes life easy. Here's how I have laid them out:



And here's the XAML document in its entirety, thus far:

<UserControl x:Class="NavigationSample.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="800" Height="200">
<
Canvas x:Name="LayoutRoot" Background="White">
<
Rectangle Width="780" Height="100" Stroke="#FF666666" RadiusY="15" RadiusX="15" StrokeThickness="2" Canvas.Top="50" Canvas.Left="11">
<
Rectangle.Fill>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#FFC4C4C4" Offset="1"/>
<
GradientStop Color="#FFFFFFFF" Offset="0"/>
</
LinearGradientBrush>
</
Rectangle.Fill>
</
Rectangle>
<
Rectangle Height="80" Width="760" RadiusY="7" RadiusX="7" StrokeThickness="2" Stroke="#FFB1B1B1" Canvas.Left="21" Canvas.Top="60">
<
Rectangle.Fill>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#FFF7D599" Offset="1"/>
<
GradientStop Color="#FFE8AF34"/>
</
LinearGradientBrush>
</
Rectangle.Fill>
</
Rectangle>
<
TextBlock Text="Home" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="49" Foreground="#FF6D6D6D" FontWeight="Normal"/>
<
TextBlock Text="Archive" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="168" Foreground="#FF6D6D6D" FontWeight="Normal"/>
<
TextBlock Text="About" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="312" Foreground="#FF6D6D6D" FontWeight="Normal"/>
<
TextBlock Text="Code" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="443" Foreground="#FF6D6D6D" FontWeight="Normal"/>
<
TextBlock Text="Slides" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="570" Foreground="#FF6D6D6D" FontWeight="Normal"/>
<
TextBlock Text="Contact" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="684" Foreground="#FF6D6D6D" FontWeight="Normal"/>
</
Canvas>
</
UserControl>

8. We need to make the buttons change color.

Before, I said that the TextBlocks don't actually do anything, and that's true. What I am going to do instead is cover each of those TextBlocks with a semi-transparent Rectangle, and that's the XAML element that is going to do all of the work. I'm also going to add the vertical gray seperators between each TextBlock, but those are just Rectangles. Nothing very exciting. You'll see it in the XAML. Here's my rectangles:

 <Rectangle Height="76" Width="109" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="23" Canvas.Top="62" x:Name="Home"/>
<
Rectangle Height="76" Width="139" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="133" Canvas.Top="62" x:Name="Archive"/>
<
Rectangle Height="76" Width="132" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="273" Canvas.Top="62" x:Name="About"/>
<
Rectangle Height="76" Width="126" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="406" Canvas.Top="62" x:Name="Code"/>
<
Rectangle Height="76" Width="122" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="533" Canvas.Top="62" x:Name="Slides"/>
<
Rectangle Height="76" Width="122" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="656" Canvas.Top="62" x:Name="Contact"/>

There are two things special about these rectangles. The first is that I have actually named them. Each one has an x:Name property, with an indication of which TextBlock it is covering. The second thing you should notice is that they have an opacity set to ZERO. This means that they are completely transparent. An opacity of 1 means that you can't see through them at all. This is the property we are going to manipulate with some code. Here's what the nav looks like now, and the XAML will follow it.



<UserControl x:Class="NavigationSample.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="800" Height="200">
<
Canvas x:Name="LayoutRoot" Background="White">
<
Rectangle Width="780" Height="100" Stroke="#FF666666" RadiusY="15" RadiusX="15" StrokeThickness="2" Canvas.Top="50" Canvas.Left="11">
<
Rectangle.Fill>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#FFC4C4C4" Offset="1"/>
<
GradientStop Color="#FFFFFFFF" Offset="0"/>
</
LinearGradientBrush>
</
Rectangle.Fill>
</
Rectangle>
<
Rectangle Height="80" Width="760" RadiusY="7" RadiusX="7" StrokeThickness="2" Stroke="#FFB1B1B1" Canvas.Left="21" Canvas.Top="60">
<
Rectangle.Fill>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#FFF7D599" Offset="1"/>
<
GradientStop Color="#FFE8AF34"/>
</
LinearGradientBrush>
</
Rectangle.Fill>
</
Rectangle>
<
TextBlock Text="Home" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="49" Foreground="#FF6D6D6D" FontWeight="Normal"/>
<
TextBlock Text="Archive" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="168" Foreground="#FF6D6D6D" FontWeight="Normal"/>
<
TextBlock Text="About" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="312" Foreground="#FF6D6D6D" FontWeight="Normal"/>
<
TextBlock Text="Code" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="443" Foreground="#FF6D6D6D" FontWeight="Normal"/>
<
TextBlock Text="Slides" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="570" Foreground="#FF6D6D6D" FontWeight="Normal"/>
<
TextBlock Text="Contact" FontFamily="ROCK.TTF#Rockwell" FontSize="20" Canvas.Top="91" Canvas.Left="684" Foreground="#FF6D6D6D" FontWeight="Normal"/>

<
Rectangle Height="77" Width="1" Fill="#FFB1B1B1" Stroke="{x:Null}" Canvas.Top="62" Canvas.Left="132" x:Name="Divider1"/>
<
Rectangle Height="77" Width="1" Fill="#FFB1B1B1" Stroke="{x:Null}" Canvas.Top="62" Canvas.Left="272" x:Name="Divider2"/>
<
Rectangle Height="77" Width="1" Fill="#FFB1B1B1" Stroke="{x:Null}" Canvas.Top="62" Canvas.Left="405" x:Name="Divider3"/>
<
Rectangle Height="77" Width="1" Fill="#FFB1B1B1" Stroke="{x:Null}" Canvas.Top="62" Canvas.Left="532" x:Name="Divider4"/>
<
Rectangle Height="77" Width="1" Fill="#FFB1B1B1" Stroke="{x:Null}" Canvas.Top="62" Canvas.Left="655" x:Name="Divider5"/>
<
Rectangle Height="76" Width="109" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="23" Canvas.Top="62" x:Name="Home" MouseEnter="MouseOver" MouseLeave="MouseOut" MouseLeftButtonDown="MouseClick" />
<
Rectangle Height="76" Width="139" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="133" Canvas.Top="62" x:Name="Archive" MouseEnter="MouseOver" MouseLeave="MouseOut" MouseLeftButtonDown="MouseClick" />
<
Rectangle Height="76" Width="132" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="273" Canvas.Top="62" x:Name="About" MouseEnter="MouseOver" MouseLeave="MouseOut" MouseLeftButtonDown="MouseClick" />
<
Rectangle Height="76" Width="126" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="406" Canvas.Top="62" x:Name="Code" MouseEnter="MouseOver" MouseLeave="MouseOut" MouseLeftButtonDown="MouseClick" />
<
Rectangle Height="76" Width="122" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="533" Canvas.Top="62" x:Name="Slides" MouseEnter="MouseOver" MouseLeave="MouseOut" MouseLeftButtonDown="MouseClick" />
<
Rectangle Height="76" Width="122" Opacity="0" Fill="#FFFFFFFF" Stroke="{x:Null}" Canvas.Left="656" Canvas.Top="62" x:Name="Contact" MouseEnter="MouseOver" MouseLeave="MouseOut" MouseLeftButtonDown="MouseClick" />
</
Canvas>
</
UserControl>


9. We need some event handlers.

Each of the Rectangles that we just created need event handlers so that we can do things when the user rolls over them, as well as clicks on them. All we need to add to each of those 6 Rectangles is this code:

MouseEnter="MouseOver" MouseLeave="MouseOut" MouseLeftButtonDown="MouseClick"

I actually already added them for you in the XAML from step #8, but I want to make sure you know why they are there. We're going to define the methods in our next step.

10. Let's write some event handler methods!

So our XAML is technically done. If our designer wanted to change stuff later, he/she can do whatever he/she wants. We just need to write some methods in the Page.xaml code-behind file, and we're done with this little project.

Before we do that, however, I've got one small task for you. In order to do this efficiently, we're going to need to add a reference to this Silverlight project. We're adding System.Net. To add a reference, just right click on the "References" folder in your project, and choose "Add Reference..." In the box that appears, just choose System.Net, and click "OK."



The reason we're doing this is so that we have access to the HtmlWindow and HtmlPage classes. We'll be using those in a method to redirect our user to another page.

Our MouseOver and MouseOut methods are very similar. One is going to add some opacity to our Rectangles, and the other will remove it again. This will give us a very nice rollover effect when the user's mouse moves over each nav element. Here's what those methods look like:

 private void MouseOver(object sender, MouseEventArgs e)
{
Rectangle activebox = sender as Rectangle;
activebox.Opacity = .2;
}

private void MouseOut(object sender, MouseEventArgs e)
{
Rectangle activebox = sender as Rectangle;
activebox.Opacity = 0;
}


Our (kinda) final method is the one to handle clicking on the nav. Ideally, when a user clicks on a nav element, they expect to be whisked away to a new page. And that's the experience we are going to provide them. Here's the method:

 private void MouseClick(object sender, MouseButtonEventArgs e)
{
Rectangle activebox = sender as Rectangle;
if (activebox != null)
{
switch (activebox.Name.ToString().ToUpper())
{
case "HOME":
LaunchNewPage("http://jeffblankenburg.com/default.aspx");
break;
case "ARCHIVE":
LaunchNewPage("http://jeffblankenburg.com/archive.aspx");
break;
case "ABOUT":
LaunchNewPage("http://jeffblankenburg.com/aboutjeffblankenburg.aspx");
break;
case "CODE":
LaunchNewPage("http://jeffblankenburg.com/code.aspx");
break;
case "SLIDES":
LaunchNewPage("http://jeffblankenburg.com/slides.aspx");
break;
case "CONTACT":
LaunchNewPage("http://jeffblankenburg.com/contact.aspx");
break;
}
}
}

private void LaunchNewPage(string URI)
{
{
HtmlWindow window = HtmlPage.Window;
Uri uri = new Uri(URI);
window.Navigate(uri);
}
}


You'll see that the cases in the switch statement should exactly match the names of the 6 Rectangles that we are using, but capitalized. Since I'm never certain exactly which way I capitalized my names, I find it easier just to compare those names converted to all capital letters. That's what the .ToUpper() is for in the switch statement.

You should also see that we call a method named "LaunchNewPage()" in each case. I have extracted the page redirect into its own function. The reason for this, at least initially, was because I wasn't sure if I wanted to open new windows for each click, or if I just wanted to redirect the user in the same browser window. By extracting this functionality, I can easily change it later for all of them, without having to touch each individual case. I do this for things like alert() in javascript as well. That way, if later, I want to make those alert boxes something nicer, like a popup DIV or even another window, I can do it easily.

So there you go! We've got a working navigation!

Click here to see the Silverlight Navigation working...

Click here to get the source code for this entire solution...

kick it on DotNetKicks.com

Labels: , , , , , , ,

posted by Jeff Blankenburg, 9:46 AM | link | 5 comments |

Giving You The Bird

Thursday, December 18, 2008

I guess I haven't really promoted the redesign of my blog very well, as several folks on Twitter have only recently discovered it. So, if you're reading this via RSS, do me a favor and head over to my website for a moment. jeffblankenburg.com

There's a few Silverlight animations going on at the top of my blog, and I've been asked several times if that was hard to do. The answer is NO. It's actually incredibly simple. Instead of doing a step-by-step tutorial this time, however, I've decided to venture into the screencast world. You should see a video player below. If you don't, it's likely I did something wrong. This is a learning process.



Again, if you go to my blog directly, you should be able to see it just fine. How this format is received will directly affect whether I will do more of these. I am looking for feedback on three things:

  1. What you think of my site's redesign.
  2. What you think about development tutorials (do you find this kind of content useful?)
  3. Whether you prefer text-based or video based information.

Labels: , , , , ,

posted by Jeff Blankenburg, 2:45 PM | link | 3 comments |

United States Map in XAML

Monday, November 17, 2008

I've been asked by a couple of folks how they might get started creating a map of the United States in XAML. Having done some mapping work in my past, I know how difficult it can be to create the states as individual elements, but arranged to represent the shape of the country. It's challenging to say the least.

So, having said that, I wanted to make sure that everyone that needs the United States rendered in XAML can have it. I found this on the blog of Maciej Skierkowski, where he was facing the same problem. It's my understanding that he created this, and here's his post on the reason.

Download the map of the United States in XAML here.

Labels: , ,

posted by Jeff Blankenburg, 10:14 AM | link | 1 comments |

Blankenthoughts: A Popular History Tour

Wednesday, October 22, 2008

Inspired by the most recent post over at Advergirl (a friend of mine), I have decided to list out links to the 10 most popular posts from the entire 2+ year history of my blog. The reason for this is to introduce some of my older (but still useful) articles to some of my newer readers. So here goes:

10) Calling Javascript From Silverlight 2

This is another in my series of tutorial posts, which walks you through creating a Silverlight application that can both call, pass values to, and retrieve values from a Javascript method in the web page host. An invaluable read for any Silverlight developer.

9) Extraordinary Nut Snack

This is a commentary on the commercials from Frito-Lay on their new line of snacks. It includes a video of their first try at commercials. Beautifully done in CGI, the almonds fall like dominoes. And then they say the title of this post. Your mind will wander.

8) CAPTCHA the Flag

This is a complete walkthrough on implementing Asirra, a new CAPTCHA control (of sorts) from Microsoft Research. It's incredibly easy to add to your application, and might even result in an adoption!

7) 6 Tips For Making Website Registration User Friendly

There are a million different websites out there, and there's a million different ways to register for an account on them. This is a list of simple suggestions for the next time you head down the "registration" path. Best tip? Make it easier for your users, not for the developer building the pages.

6) Top 10 Things New Twitter Users Need To Know To Get Followers

You only get one real chance to impress upon someone why they should follow you on Twitter. Following these rules will help you immensely.

5) Simple Resizing In Silverlight

One of the beauties of Silverlight is that it is based on vector graphics. This means that no matter what size you display them, they don't get pixelated and blurry. Vector graphics can grow or shrink to any size, and this tutorial shows you the simple way to make it happen.

4) Creating A Simple Silverlight Animation

As the creator of the CodeMash logo, I was excited when I found out I could convert my Adobe Illustrator file to XAML. Once that was completed, the next logical step was to animate the gears. This tutorial shows you how to do that, as well as a quick tour around Expression Blend.

4) Left Outer Join In LINQ

As someone who has a hard time getting out of a traditional SQL mindset, when I started using LINQ, the question of how to emulate a left outer join immediately confronted me. This outlines the simple way to do just that.

3) I Hate Windows, I'm Moving To Windows Mojave

This was briefly written to announce the Windows Mojave website and advertising campaign. It has certainly has its praises and criticims, but this post got more traffic in one day than any other post has ever gotten.

2) TUTORIAL: Creating a WCF Service for Silverlight 2 and SQL

One of my first "tutorial" posts, this hit the ground running, and hasn't looked back. It's an excellent beginning example of how to get Silverlight talking to a web service that accesses a SQL database.

1) General Ionics: Fake or Fab?

This article was written while I was buying a water filtration system for my home. While not technical in nature, this has been, by far, my most popular post to date.

Labels: , , , ,

posted by Jeff Blankenburg, 8:35 PM | link | 0 comments |

TUTORIAL #5: Calling Javascript From Silverlight 2

Tuesday, September 23, 2008

In this post, I want to show you how incredibly simple it is to call a Javascript function from the managed code of your Silverlight application. We'll also be able to retrieve a value from that function, and return it to Silverlight. If you're just hunting for the syntax, just jump to step #6. This post covers creating everything from scratch, in both VB and C#.

1) Create your Silverlight project and sister web site.

I've already documented creating a new Silverlight project here, so I'll let you read that one first, if necessary.

2) Let's write a "legacy" Javascript function.

We need a JS function to call, so let's make it interesting. Let's say that I have some code from a previous app that determines all of the prime numbers from 1 to 500. I don't necessarily want to rewrite that, so let's just reuse it. Here's the code:


//The purpose of this code is to find all of the prime numbers under 500.
//The definition of a prime number is one that is only divisible by 1 and itself.
//We are utilizing the Sieve of Eratosthenes to enhance our algorithm.
var primeArray = new Array();
var primecounter = -1;
var primeFlag = true;

function getPrimes(useri){
     primeArray.length = 0;
     primecounter = -1;
     var i = 500;
     if (useri != ""){
          i = useri;
     }
     for (j=1;j<=i;j++) checkForPrime(j);
          return primeArray.join(" ");
}
function integerCheck(newvalue){
     var regexp = /(^\d\d*$)/;
     if(regexp.exec(newvalue)) primeFlag = false;
}
function checkForPrime(j){
     primeFlag = true;
     for (k=0;k<=primecounter;k++){
          if ((primeArray[k] != "")&&(primeFlag)){
               if ((j/primeArray[k] != 1)&&(j/primeArray[k] != j)){
                    integerCheck(j/primeArray[k]);
               }
          }
     }
     if (primeFlag){
          primeArray[primecounter+1] = j;
          primecounter++;
     }
}


3) Add that JS code to our web page.

Just add a <script> block in the <head> of your web page, and put the above code inside. Done!

4) Now we need to write some XAML.

Open your Page.xaml file that was created for you, and let's add a button. We'll use this button's event handlers to call our Javascript function eventually. To add a button, here's the XAML I am using inside of the <Grid> I was provided:


<Button Width="100" Height="50" Content="Get Primes!" />


5) Add an event handler to our button.

In our button, add the "Click" property, and Intellisense will prompt you to create a "New Event Handler." This will create the method in the code behind file for you. Here's the new button XAML:


<Button Width="100" Height="50" Content="Get Primes!" Click="Button_Click" />


6) Time to call that Javascript function.

Jump into the code behind file for your XAML (page.xaml.cs or page.xaml.vb by default). There's a new method called Button_Click for you. We are going to write ONE line of code to make this happen. And here it is:

C#

HtmlPage.Window.Invoke("getPrimes");

VB

System.Windows.Browser.HtmlPage.Window.Invoke("getPrimes")


I kinda lied though on the 1 line of code thing. For C#, we also need the "using System.Windows.Browser;" statement. The "getPrimes" value we are passing is the name of the Javascript function we want to call. But this only gets us halfway there. My JS function creates a list of prime numbers and then sends them back as a return value. So we need to actually do something with this value.

7) Refactoring our code to use the return value.

So we know we can call a Javascript function, but returning the value is going to be a little more challenging. We need to capture the return value, cast it as a string (everything from Javascript is assumed to be an object), and display it in our Silverlight app. But let's make it a little more interesting. Let's also change things to pass parameters to our JS function as well.

First, we need some new XAML elements. I've added a <TextBlock> to my XAML page to display the primes, as well as a <TextBox> to gather the number of primes the user wants to generate. Here's the new XAML code:


<StackPanel x:Name="LayoutRoot" Background="White">
     <TextBlock Width="400" Text="Primes to what number?" TextAlignment="Center" />
     <TextBox Width="100" Height="24" x:Name="primecount" Margin="0,0,0,10" />
     <Button Width="100" Height="50" Content="Get Primes!" Click="Button_Click" />
     <TextBlock x:Name="primebox" Width="800" TextWrapping="Wrap" />
</StackPanel>

And now here's my new C# and VB code inside my Button_Click methods to pass our value and display this data:

C#

string primeArray = (string) HtmlPage.Window.Invoke("getPrimes", primecount.Text);
primebox.Text = primeArray;

VB

Dim primeArray = System.Windows.Browser.HtmlPage.Window.Invoke("getPrimes", primecount.Text)
primebox.Text = primeArray.ToString


What will happen in this scenario is that if the user provides a value, we will use it, and if they don't, we'll default to 500.

8) So let's run it!

That's it! We've successfully called a Javascript function from Silverlight (in both C# and VB), retrieved the value it created, and displayed it in our application. We also passed specific parameters to that Javascript function to influence its behavior. Click the Demo button to see it in action.



9) Source Code Links

I've provided the source code for this example in both C# and VB. Just click the appropriate button.

C#.NET Source Code VB.NET Source Code

kick it on DotNetKicks.com

Labels: , , , , , ,

posted by Jeff Blankenburg, 12:21 PM | link | 3 comments |

TUTORIAL #4: Showing Non-Silverlight Content To Users Without The Plugin

Monday, September 22, 2008


I just recently updated the navigation on my blog (http://www.jeffblankenburg.com) to be a nice Silverlight control, and realized that I was not really providing an optimal experience for those people that don't have the plugin installed. So since I had to go through it, I thought I would share with you how simple this actually is.

When you add a new Silverlight control to your page, this is what the code will look like:


<div id="silverlightControlHost">
     <object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="880" height="60">
          <param name="source" value="ClientBin/JeffBlankenburg.com.xap"/>
          <param name="onerror" value="onSilverlightError" />
          <param name="background" value="white" />
     </object>
</div>


How To Add Your Non-Silverlight Content

Here's all you need to do to get it to work. Inside the <object> tag, after all of the <param> tags, just add your HTML. In my example, I have a different navigation in HTML for non-Silverlight users. It will display this content when the Silverlight plugin is absent.

Here's the new example, with my content included:


<div id="silverlightControlHost">
     <object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="880" height="60">
          <param name="source" value="ClientBin/JeffBlankenburg.com.xap"/>
          <param name="onerror" value="onSilverlightError" />
          <param name="background" value="white" />
          <div id="sitetitle"><h1><a href="http://www.jeffblankenburg.com" class="style3">Blankenthoughts</a</h1><p class="style4"><strong>These are my thoughts. Nothing more.</strong></p></div><div id="menu"><a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;"><img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/></a></div>
     </object>
</div>


How do I test this? I have the plugin installed!

That's easy in IE8. Just go to:

Tools > Internet Options > Programs > Manage Add-ons

and choose the Silverlight plugin. You can temporarily disable it there. Great new feature. Here's a picture of the screen (click to enlarge).



There you go. You can now create custom HTML to display for your users that have not yet installed the Silverlight plugin. I'd recommend letting them know they're missing out on the full experience, however, or they will never find your cool Silverlight control.

kick it on DotNetKicks.com

Labels: , , , ,

posted by Jeff Blankenburg, 11:41 AM | link | 2 comments |

DevLink '08 in pictures...

Monday, September 01, 2008



I created a quick mashup in Popfly using my Flickr account. Enjoy!

(I highly recommend the full screen option. These pictures are BIG.)

Labels: , , ,

posted by Jeff Blankenburg, 6:06 PM | link | 1 comments |

Consuming Web Services In Silverlight

Monday, August 11, 2008

UPDATED: Due to some awesome technical difficulties, I will yet again not be streaming this broadcast live. However, I am recording it, and will be making available as soon as possible. My apologies for the inconvenience.

You may have seen my post about WCF with Silverlight a few months ago, but on Tuesday night, John Stockton (no, not the point guard) will be presenting his take on this at the Cleveland .NET Special Interest Group.

The meeting takes place at the Microsoft offices in Independence, OH on the second Tuesday of every month, which happens to be tomorrow. The meetings start at 5:45, and usually end around 7:30 PM.

After the meeting, there's a group of us that head over to the Winking Lizard on Rockside Road for a late snack and some beverages. I have some of the best conversations with these people, both technical and not-so-much. Make an effort to carve some time out of your busy schedule tomorrow night to participate in both events.

If you can't make it due to deadlines/family/car trouble/agoraphobia/atomic weight, I am also going to be streaming the presentation LIVE over the Internet. All you need to do is open a browser, and go to my page at ustream.tv. You can also watch it on my blog, in this post. I've embedded a player for your convenience. You don't need to register, just show up and get your learn on.

Labels: , ,

posted by Jeff Blankenburg, 6:48 PM | link | 1 comments |

NBC Olympics - In Silverlight 2!

Friday, August 08, 2008


NBC will start their broadcast of the 2008 Summer Olympics today. They have partnered with Microsoft to use Silverlight as their video delivery medium. You will be able to watch the events live from Beijing, with multiple events (or multiple angles of the same event) in your browser.

You can even participate in some social networking as well. It will show you what the most popular video feeds are. I'm looking forward to trying it out...

You can watch all of it at http://www.nbcolympics.com, starting today!

Labels: , ,

posted by Jeff Blankenburg, 10:31 AM | link | 2 comments |

I Like To Talk...

Tuesday, June 24, 2008

I like speaking in public. I really enjoy it. But it's been far too long since I've done it. And my next scheduled talk isn't until the end of August, at DevLink.

I'm posting this message to let the world know that I'm ready to get back in the game. Please contact me at jeffrey.blankenburg@microsoft.com if you would like me to come talk to your developers, whether that's internal to your company, or at a user group in your community. I will do my best to accomodate all requests. I've got several new talks ready, as well as a few older favorites that audiences enjoy.

Here they are:

* Building Next Generation Web Apps With Visual Studio 2008
This talk is an overview of Visual Studio 2008 and some of the great new features it has to offer. This includes tools and techniques ranging from the Split view design pane to effectively using LINQ.

* Silverlight 101: The Basics
This talk really is an introduction. We'll talk about XAML, build a basic application, and show the integration with Expression Blend. I would recommend this for any group that wants to get their feet wet with Silverlight.

* Silverlight 301: Way More Than A Spinning Button
In this talk, we will learn how to build a Silverlight application that talks to a SQL server through a WCF web service. We will render the content in a visually appealing way using XAML. And if you ask nicely, I'll even spin a button for ya.

* Cool Microsoft Stuff: The Technologies You Have To Try
This is an overview of some of the amazing things Microsoft is working on behind the scenes. Some of them are available in beta form, but you're guaranteed to see something you've never seen before. This includes technologies like Photosynth, Deep Zoom, and Live Mesh.

* XNA Anyone?
This talk will walk you through the basics of game development using XNA as the platform. We will also talk about game development for the Zune.

Labels: , , , , ,

posted by Jeff Blankenburg, 10:21 AM | link | 0 comments |

TUTORIAL #1: Creating a WCF Service For Silverlight 2 and SQL

Thursday, June 19, 2008

Today I'm going to show how to create a simple WCF service, and consume it from a Silverlight application. This is something you are going to need to do quite often, and if for no other reason, I am documenting this here so that I have it as a reference.

The first thing we need to do is create a Silverlight application. (In order to have all of the Silverlight 2 prerequisites, make sure you visit this page.)

1) I'm going to start from the beginning. First, we need to create a new Silverlight project. I'm naming mine JBWCFService.

Creating a new Silverlight project

2) We will then be prompted to create a web project to accompany our Silverlight project. I choose a Web Application Project from the dropdown.



3) Here is a view of what my solution explorer looks like after the projects are created. I have a Silverlight project called JBWCFService and a Web Application project called JBWCFServiceWeb, not surprisingly.



4) Next, I want to create a SQL database from which to get my data from. I'm not going to walk through all the steps of adding tables, columns, and data. You can certainly find that elsewhere. Here's my adding the SQL database to my project though...



5) OK, it's time to create our service. I'm naming my service MyNewService. It's just another thing to add to our project, so here we go:



6) Once the new service has been created, you will have a few new files in your project. In my case, they are named IMyNewService.cs, MyNewService.svc, and its code-behind, MyNewService.svc.cs. By default, the interface (IMyNewService.cs) will be open and ready for editing. They create a DoWork() method for you, but we're going to delete that and do something more interesting in a little while. First, we need to get LINQ up and running against our data. I am naming mine LINQClasses.



7) In addition to adding the class files necessary, this will also open the LINQ design surface by default. We can just drag items from our data structure right to the left half of the surface, creating ORM class structures that represent our data. In my example, I only have one table, profile, but we can do this for all of our tables, and stored procedures can be dragged to the right half of the surface, creating methods. I have already dragged my table over in the next screenshot (click to enlarge).



8) We also want to make sure that our data is unidirectionally serializable (I like big words). By clicking on the design surface (not one of the table boxes), you can get to the properties of the DataContext, and change the Serialization Mode to "Unidirectional."



9) Now we need our Silverlight project to become aware of our WCF service running in the web application project. To do this, we just need to add a new service reference to the Silverlight project. Click the "Discover" button to find it automatically. This will also automatically spin up a web server for your service to run in. I named my service reference MyNewServiceReference.



10) Ready to write some code? To this point, everything has been handled automatically for us. Now we have to get our hands dirty. Let's go back to our Service interface (IMyNewService.cs). In there, let's get rid of that DoWork() method. Instead, our method is going to return a List of profiles from the database, based on our new classes that were created for us. Because this is an interface, we don't define the actual functionality of the method here, just it's signature. I named my method GetProfilesByLastName.



11) Ok, that was exhausting. Let's have the IDE write some more code for us now. Let's open the code-behind file for MyNewService.svc (MyNewService.svc.cs). You can see that it inherits from the interface we just defined, so right click on the name of the interface, and have it implement the interface for you.



12) Now you've got the shell for the method. We just need to tell this method what to do. Here's where the LINQ comes into play. We need to get a reference to our DataContext from earlier, and then I wrote a simple query to retrieve names from the database based on a last name query. Finally, we return our list of data.



13) Each time we update our service, we will need to update our service reference in the Silverlight project, so that it sees our new methods. Just right click on the service reference and choose "Update Service Reference." Also, we have one small change we need to make to our web.config file as well. If you've been following the instructions, then you can scroll down to the bottom of your web.config and look for the <endpoint binding="wsHttpBinding" /> property. Silverlight only currently supports basicHttpBinding, so we need to change it to that.



14) Next, we need to add one more reference to our Silverlight project before we can finally start working with the XAML. We need to add a reference to System.Windows.Controls.Data so that we can use the DataGrid control in our interface.



15) XAML time. Kinda. We need to include that reference as a namespace in our Page.xaml document. OK, now we can add some controls to our page. I also added a Button, a TextBox, and a DataGrid, inside a couple of StackPanels, for layout purposes.



16) Now, we need to call that method in our service and populate that grid. The first thing we need to do is instantiate our ServiceClient. Now, since we are calling this service asynchronously, we also need to set up an event handler to know when our data has returned so that we can update the DataGrid. There's an excellent bit of shorthand for creating this code automatically. My screenshot shows all of the code I will need, but for the line that starts:

sc.GetProfilesByLastName +=

I only actually typed what is above. After that, I pressed the Tab key twice. The first press of Tab actually finishes out my EventHandler statement. The second Tab press creates my EventHandler method, so that I can add the guts. Finally in my Button_Click method, I need to call the GetProfilesByLastName asynchronously, passing in the value from my TextBox, named DataEntry.



17) The last little touch we need to put on this application is the actual binding of the data to our DataGrid, and we'll do that in the new EventHandler method that was created for us. There's just one line of code in the method:

DataGrid.ItemsSource = e.Result;



So, there you have it. We've created a WCF service that uses LINQ to talk to a SQL server, and a Silverlight 2 application that consumes that service and renders the result. Not bad for 17 steps, and only a few lines of code.

Click here to download the solution files.

Labels: , , , , , , ,

posted by Jeff Blankenburg, 11:34 AM | link | 9 comments |

Silverlight 2 Visibility Bug With The Canvas

Wednesday, June 18, 2008

So I encountered a bug today. A real-life, this-hasn't-been-fixed-yet bug in Silverlight 2 Beta 2. And I gotta think it's pretty common. After all of my posting on layout options, I think it's my responsibility to mention this one. It is also documented on the Silverlight forums, but I want to make sure it's shared here as well...

Much of what I am doing for my pet Silverlight 2 project requires me to show/hide different canvases, depending on which "page" you are on within my site. I've seen some Silverlight sites that are actually just different SL apps, and links actually take you to a seperate .aspx page for each one. I wanted to keep the user experience without any postbacks. All AJAX. No wavering from my page. Because of this, each navigation button just hides everything and shows the section it represents.

So each "page" is represented as a canvas. And for the simple example below, it works perfectly.



However, when your canvas contains elements that derive from Control, you don't get the behavior you expect. Here's my canvas with real stuff in it:



What I am finding is that my canvas just doesn't show up. In my code, I know my syntax is correct, because it works for all of the simple canvases like the first one I showed. The moment I add a Button, TextBox, Radio Button, User Controls, etc. the Canvas no longer will change its Visibility property from Collapsed to Visible. This, it would seem, is a major problem. However, there's a pretty simple workaround for this.



Click here to see the example running.

By making my base element for this function something other than a Canvas, it works perfectly. In my example, I have used a StackPanel, and just put my Canvas right inside it as the only element. In this example, all of the contents of my "page" will display as expected now.

Sure, it's a little work-around-y, but it gets the job done until this bug is corrected.

Has anyone else encountered this? What was your solution?

Labels: , , , ,

posted by Jeff Blankenburg, 2:28 PM | link | 3 comments |

Silverlight Layout Options - Grid (Part 3 of 3)

Friday, June 06, 2008

(See Part 1 and Part 2 first...)

In the third and final installment of this series on Silverlight Layout, we are going to be discussing my preferred option for interface creation: The Grid. In many ways, I would compare this to table based layout in HTML (which is generally a bad word), but I will come to its defense in Silverlight today.

There are many reasons why table-based layouts should not be used in HTML. A few of them are:

1) Tables are very heavy. With all of the <tr> and <td> tags you need, the page bloats quickly.

2) CSS is the right way to do it. Once you harness the power of CSS, you have far greater control of your layout (not to mention accessibility) than you do with tables.

3) Tables are very difficult to manipulate once they are in place. If you've ever tried to move things around in a legacy table layout, you know what I'm talking about.

The reason I am recommending this type of layout is because those problems have been addressed in Silverlight with the <Grid>. So let's take a look at the code.



You'll notice that this doesn't really look like HTML table layout that you've seen in the past. Instead, we've seperated (still in the same file, mind you) the content from the layout. We don't have to wrap each element in a set of table tags. We define a grid, and then we assign each element to a cell of that grid. I've also turned on the ShowGridLines attribute, so we can see exactly what the grid looks like. We can also assign height and width values to the cells of the grid, up to and including the wildcard "*" character. This tells the application to use the rest of the remaining space for that cell. If you have more than one wildcard cell, it will split the unclaimed space evenly between them. Please note that the grid starts with 0,0, not 1,1. So our Red Rectangle is assigned to Grid.Cell="0" and Grid.Row="0" which puts it in the top left corner. Each of the respective rectangles after that is assigned to their respective grid location as well. The design pane of Visual Studio 2008 looks like this with the XAML I just used:



You'll notice that the Black rectangle is missing. That is the one assigned to the wildcard space. In the design pane, there's not a Canvas width and height defined. In the XAML, I did not specify a width and height for my Grid. This causes it to fill the entire space of the window it is rendered in. When we run the application, however, you'll see that the black box is, in fact, there, and takes up the rest of your browser window.

In my next post, I will talk about using templates to create "styles" that can be reused by your XAML elements.

Labels: , , , , , , ,

posted by Jeff Blankenburg, 8:36 AM | link | 0 comments |

Silverlight Layout Options - Stack Panel (Part 2 of 3)

(See Part 1 first...)

Today we are looking at a second way to lay out your interface in Silverlight. This will be far more familiar to the CSS fanatics out there. The primary concept is simple...we'll be using a StackPanel control to position our elements.

For those of you less familiar with CSS, this is more of a flow-based layout. As the size of the Silverlight container grows and shrinks, you will find that the elements will move to accomodate that space. I, personally, would not recommend approaching your entire interface with this technique, but it certainly makes sense for small portions, like navigations and lists of data.

Most of our positions will be determined by manipulating the margins of the individual elements on the page. In doing so, we can place our elements specific distances apart without having to specify their exact position on that page.

In the example below, I have 6 buttons that I want to arrange in a 3x2 block. I start with an outer stack panel that, by default, will stack my elements vertically. However, I want to have two rows of 3 buttons each, so I am going to nest two more stack panels. Each of these will have the Orientation attribute of the StackPanel set to Horizontal, to create the rows.



For demonstration purposes, I also modified the margins of a few of the buttons, just to show that we are merely stacking these elements. This is not a grid, or table, and certainly not absolute positioning. These elements are merely stacked, either horizontally or vertically, with margins as the leverage to move things around a bit.

NOTE: I have a major complaint about how margins were implemented in Silverlight.

Again, for those of you familiar with CSS, the de-facto standard for specifying margin sizes was one of two formats:

margin-left:10px;
margin-right:10px;
etc.

OR

margin:0 10px 0 10px;

Each of those examples would have given you a 10 pixel margin on both the left and right of the element you were styling. In the second example, we are using a bit of shorthand to specify ALL of the margins in one line. They start with the top, and go clockwise. margin:Top Right Bottom Left;

In the margin implementation for Silverlight, it would appear that they also offer a shorthand version for margins (actually, the only version is shorthand), and they did not follow the standard convention mentioned above. Instead, they chose to use Margin="Left, Top, Right, Bottom". I've not yet talked with the team to see why this convention was chosen over something more familiar to developers, but if I can find an answer, I will post it here.

(continue to Part 3...)

Labels: , , , , ,

posted by Jeff Blankenburg, 8:35 AM | link | 2 comments |

Silverlight Layout Options - Canvas (Part 1 of 3)


There are many decisions to be made when you're building a new application, and Silverlight introduces some new (but old) paradigms when it comes to the layout of your interface.

In this first part of three articles, we're going to be talking about the <Canvas> option. I equate this to a more familiar concept in HTML known as absolute positioning. Each element will be given its own specific location on the page, and nothing but code can move them. This is also one of the downfalls of the <Canvas>, but for many apps, this may not matter.

With elements absolutely positioned, things just don't adjust. If a user resizes their browser, the elements don't move. If a user tries to see your application on a smaller screen than you anticipated, part of the app is going to be hidden. (Think mobile phones, for example...if you position everything out to fit in a window 800 x 600, that 320 x 200 screen is not going to show very much).

However, this is still one of the fastest ways to get your elements positioned on a page, and the taboos that came with absolute positioning in CSS are erased, because we're now developing in a universal plugin, not 17 flavors of browser and platform combinations.

So how do we do it? Here's some example code:

Click to see this running...

As you can see, it's pretty straightforward. We have a button, an ellipse, and a rectangle, and their positions are defined by the Canvas.Left and Canvas.Top attributes. You can also nest <Canvas> tags, and the Left and Top attributes apply to the immediate parent of the element you are positioning.

Click here to see the code above running in a browser.

(continue to Part 2...and Part 3...)

Labels: , , , ,

posted by Jeff Blankenburg, 8:34 AM | link | 0 comments |

How About Some Code? Simple Scaled Resizing In Silverlight 2 Beta 1

Saturday, April 05, 2008

I've been talking technology for a while here, but it's about time I start adding some value. I already mentioned the JUXtapose blog, so get over there for podcasts on User Experience and the technologies I use to make my UX and UI better.

Today, I want to talk about Silverlight 2 (Beta 1). One of the things that always frustrated me when creating a new application is that nobody ever wrote a good example of how to get my Silverlight application to scale with the random sizes of my user's browsers. As long as I stay vector based, this application should look the same at 640x480 and 1280x1024. And if it makes sense to have it on a mobile phone, then let's use the same application there too.

Today, my friends, I've got the simple steps you need to make your Silverlight 2 application scale effectively. I'll start this tutorial after you've created your default application (there's a great walkthrough on that here by Jesse Liberty).

I am using Visual Studio 2008, and Microsoft Silverlight Tools Beta 1 for Visual Studio 2008. My .entire solution can be downloaded here, so you can compare the changes I have made to a default project.


Step 1


If you followed the usual steps, your project should look something like mine.
Solution Explorer for this project.
We're only going to be working in two files for this: Page.xaml, and its code-behind file, Page.xaml.cs. First, let's take a look at the Page.xaml file, because more of our work will be code, not markup. Below is a shot of the entire XAML file (click to enlarge).
page.xaml contents
The only additions I have made to this file are the entire <canvas.rendertransform> section. I've also made the rootCanvas red, so that we can see it. One other thing that I have to credit Matt Casto for finding...you MUST define an initial size for your RootCanvas. Mine is 800x600, but you can use any size you'd like.


Step 2


Now we've got a little code to write, but it's honestly pretty straightforward. We've got four things to add:

  1. an event handler for when the browser is resized.

  2. a Page_Loaded method to intialize everything.

  3. a proxy method for resizing our Silverlight control initially.

  4. a Resize() method for doing the heavy lifting.


Here's a screenshot of my entire application namespace within the page.xaml.cs file (click to enlarge).
page.xaml.cs contents

First, we need to create a couple of variables. primarily, I need variables for the original height and width of my control before I get started. You'll see why in a moment, but it's basically to retain the "aspect ratio" of our control.

Second, in my "main" method, Page(), I route a new RoutedEventHandler to my Page_Loaded method when the XAML loads.

this.Loaded += new RoutedEventHandler(Page_Loaded);


Third, I have to create my Page_Loaded method. Here, I need to capture the original height and width, and I also add a new event handler to my application when the "host.content" = browser is resized. Finally, I call my Resize() method.


void Page_Loaded(object sender, RoutedEventArgs e)
{
_originalWidth = RootCanvas.Width;
_originalHeight = RootCanvas.Height;
Application.Current.Host.Content.Resized += new EventHandler(Content_Resized);
Resize();
}


Fourth, now that I have a new event handler pointing to Content_Resized(), I should probably write that method too. It just passes the call along to my Resize() method.


void Content_Resized(object sender, EventArgs e)
{
Resize();
}


Fifth and finally, I need to write my Resize() method. This is slightly more complicated than you might expect, but there's a reason. We need to capture the width and height of the new browser size. That's what currentWidth and currentHeight are for. uniformScaleAmount is what makes this complicated. We want to scale this thing uniformly, that is to say, if the application was originally 800x600, we want to keep a 4:3 ratio at all times, rather than stretching the app to fill the space allowed. Once we have determined the appropriate scale constant, we then also want to keep this app centered both vertically and horizontally in the browser as well. The last 4 lines of the code handle this, by altering the size of the overall control.


double currentWidth = Application.Current.Host.Content.ActualWidth;
double currentHeight = Application.Current.Host.Content.ActualHeight;

double uniformScaleAmount = Math.Min((currentWidth / _originalWidth), (currentHeight / _originalHeight));
RootCanvasScaleTransform.ScaleX = uniformScaleAmount;
RootCanvasScaleTransform.ScaleY = uniformScaleAmount;

double scaledWidth = Math.Min(_originalWidth * uniformScaleAmount, currentWidth);
double scaledHeight = Math.Min(_originalHeight * uniformScaleAmount, currentHeight);
RootCanvasTranslateTransform.X = (Math.Min(RootCanvas.ActualWidth, currentWidth) - scaledWidth) / 2d;
RootCanvasTranslateTransform.Y = (Math.Min(RootCanvas.ActualHeight, currentHeight) - scaledHeight) / 2d;
}


Please give this a try on your next application. You should be able to use this on any size Silverlight application, and as long as your creative assets can handle scaling to any size (read: vector), your application should look great at all sizes. Please leave me a comment if you give this a try...I want to know that I helped someone out!

Labels: , , , ,

posted by Jeff Blankenburg, 8:42 PM | link | 5 comments |

JUXtapose

Thursday, April 03, 2008

I know I've talked about this podcast series before...but it's growing. And it's got a new home. http://www.juxtaposeblog.com



JUXtapose stands for Jeff on User Experience, and the podcast series is about exactly that. My thoughts on UX, and the tips and tricks you can use in your applications to make them more effective for your users.

I'm starting a whole set of videos on creating Silverlight 2.0 applications. These will center around creating a NCAA-tournament style site, with user management, a slick interface, and plenty of data and web services to make everything happen. I hope you'll check it out.

You can subscribe to my RSS feed here: http://feeds.feedburner.com/juxtaposeblog/KnIR

Labels: , , ,

posted by Jeff Blankenburg, 11:53 AM | link | 0 comments |

Columbus Lightning Talks

Thursday, February 28, 2008

Tonight at the Columbus .NET Developers Group (CONDG), they are having 8 lightning talks as their presentation. Lightning talks are basically 10-15 minute presentations that go one after another, with 1 minute breaks for setup/teardown.

Here are the subjects that were presented:

Steve Horn - ADO.NET
Matt Casto - Silverlight (consuming ADO.NET)
Amanda Laucher/James Bender - F#
Steve Harman - Rhino Mocks
Brian Sherwin - Log4Net
Jon Kruger - LINQ to SQL
John Vottero - PowerShell 4 Devs

These presentations were also videotaped, and will be made available on the CONDG website.

Also, in the early housekeeping, there were two major announcements made:

1) Brian Prince has accepted the Architect Evangelist role with Microsoft. He'll be working alongside me in the Heartland.

2) Carey Payette was elected the new president of CONDG. Congratulations Carey.

Labels: , , , , , , , , , , ,

posted by Jeff Blankenburg, 6:32 PM | link | 1 comments |

JUXtapose - Episode 3: Popfly: Creating Your First Mashup

Monday, January 28, 2008

posted by Jeff Blankenburg, 3:49 PM | link | 0 comments |

CodeMash Speaking Update

Thursday, January 03, 2008

In an unfortunate turn of events, Jesse Liberty (Senior Program Manager, Silverlight Development Team) fractured his shoulder a few weeks ago. He and his doctor were optimistic that he would still be able to make the trip to CodeMash (like I'm sure all of you are). His surgeon is now extremely reluctant to have him in full-on travel mode just yet, so he has been forced to cancel his trip.

Due to these circumstances, there is a gaping hole in the Silverlight content at CodeMash. I have been fortunate enough to be asked by Jesse to replace him in his absence. I'm a bit honored, and a bit panicked (I wasn't on the slate to speak until now). So there you have it....I'll be the speaker in Jesse Liberty's stead. The topics will still be the same, there will be an Intro to Silverlight and an Advanced Silverlight session at the normally scheduled time.

So, if I haven't met you, and certainly if I have, here's when I will be speaking at CodeMash.

01/09/07 9:30 AM - Coding In Silverlight
01/10/07 2:10 PM - Advanced Silverlight

Head over to the CodeMash Session Scheduler (built in Silverlight) and get me on your agenda!

Labels: , , ,

posted by Jeff Blankenburg, 9:42 PM | link | 2 comments |

Party In Cleveland!

Tuesday, December 11, 2007

UPDATED: Here is the link to the presentation.

I'm heading up to Cleveland tonight for the .NET SIG meeting.  They are deviating from their standard meeting type (speaker, pizza) to more of a holiday party style.  I'll be bringing 3 XBoxes, projectors, and a decent selection of games to play, including Halo 3, Guitar Hero III, and Project Gotham Racing 4.  But that's not really what I'm most excited about for tonight.

I'll be giving a short presentation on some of the cool things that Microsoft is working on.  I've given this a few times in the past, but it always generates more discussion and "WOWs" from the crowd than any Silverlight or WCF presentation I'm going to give.  The reason is because people haven't seen this stuff before.  And it's amazing.

For those of you not coming to Cleveland for the meeting tonight, here's a rundown of what you're going to be missing:

 

image

Microsoft Popfly - A mashup engine.  Imagine having the power to create a map with all of your Facebook friends on it.  Oh yeah, and you didn't write a single line of code.

 

image

Tafiti - I call it a research engine.  It's a new search engine interface, based on Windows Live Search, which is built entirely in Silverlight.

 

image

Microsoft Surface - a completely new model for computing.  Take one coffee table, add 400% innovation, and you've got an amazing new way to interact with files, the internet, and more.

 

image

Photosynth - Let's say you wanted to take a virtual tour of Seattle.  You could certainly look for pictures on the web, of if you really wanted to see a bunch, maybe you search on Flickr for Seattle.  Photosyth allows you (eventually) to take a set of photos from the web, and visually "stitch" them together to create a 3-D model of the space.  If you check nothing else out from this post, make this the one.

 

image

Seadragon - the technology that Photosynth is based on, Seadragon is primarily focused on showing immense amounts of image data at one time.  Their philosophy is that the only thing [in this technology era] that should restrict your ability to view large [we're talking TB] sets of images should the be number of pixels on your screen.

Labels: , , , , ,

posted by Jeff Blankenburg, 8:17 AM | link | 5 comments |

Memphis Day of .NET!

Friday, November 09, 2007


I had the opportunity to spend this past weekend in Memphis, TN. I was attending/speaking at the Memphis Day of .NET.

It started innocently enough. I arrived in Memphis (MEM), and drove to my hotel room. There, I joined up with Josh Holmes, where we headed to the speaker's pre-game dinner. It was at a location chosen by Colin Neller (the primary organizer of the event, though he had a very efficient team). We got to eat Memphis-style BBQ at a place called Central BBQ. It was outstanding. Seasoned, homemade potato chips, and some BBQ sauce to lick from your fingers. Excellent choice.

The next morning, I arrived at the FedEx Institute of Technology, and was immediately blown away by the facility. Open spaces, curves, glass & metal. Gorgeous. Then I got to see the room that the Charles Petzold's keynote would be delivered in (as well as my talk on Silverlight.) It's called The Zone, and it absolutely is. I was so inspired by what a conference facility should be that I took a short video just to show it off.

The Zone
Click here to see my video tour of The Zone




Finally, after my talk, there was a GOURMET lunch provided. We're not talking about upscale sandwiches here, either. It was roast beef, potatoes, vegetables...in short, excellent.

My hat's off to the organizers of this event. Very well done. I wish you future success in next year's event as well. (Please let me know how I can assist, if you'd like.)

Included in this post are links to the slide decks and demos that I used during the presentation.

Thanks to everyone that attended!

Silverlight 301 Deck & Demos

Innovative Microsoft Stuff Slide Deck

Labels: , , ,

posted by Jeff Blankenburg, 9:38 AM | link | 0 comments |

Looking for Stars!

Several of you have had an opportunity to catch the first couple of episodes of my video series that I am calling JUXtapose. I'm working on the next few videos here, and was thinking that I'd like to make some of you famous.

If you've done something cool, something innovative, something that when you built it, you thought, "Man, that's awesome!," then I'd like to get you on camera talking about it.

I want to capture your passion on film. I want to help you tell the world about your ideas. If it has a user interface, let's talk about it. If you found a way to take an action in your application from 32 to 2 clicks, perhaps you've been hiding in the shadows too long.

Call me, email me, comment on this blog. Whatever. Just remember, if nobody raises their hand, I'm going to start calling on people.

JUXtapose Episode Guide
11/02/2007 - Episode 1: Simple Animation Using Expression Blend
11/05/2007 - Episode 2: ComponentOne Sapphire Interviews
Coming Soon - Episode 3: HTML Controls As Silverlight Tools
Coming Soon - Episode 4: Getting Web Service Data Into Your Silverlight App
Coming Soon - Episode 5: Expression Studio Overview (Design, Blend, Web)

Labels: , , , ,

posted by Jeff Blankenburg, 9:37 AM | link | 1 comments |

You're Probably Not Interested...


1) Keynotes by Steve Ballmer and Scott Guthrie.
2) 3-4 days in Las Vegas, at the Venetian Hotel and Casino.
3) An opportunity to immerse yourself in the technologies that make up "The Next Web," and participate in a 72-hour conversation about the future of web technologies.

OK, since I'm sure that list appeals to very few of you, I'll be brief.

I'm describing Microsoft's MIX 2008 conference. I had the good fortune to attend last year, as an attendee, and had an amazing time. Silverlight was announced, for one. I had an opportunity to meet some incredible speakers, technologists, and Microsoft influentials those days. I had an opportunity to give over $200 of my own, hard-earned money to complete strangers at the poker tables.

In short, it was the best conference I have been to. My expectations are riding pretty high that v2008 will not disappoint. With that, registration is now open.

So, mull it over with your Manager. Blackmail your Boss.* Persuade your Project Manager. Discuss it with your Director. I'd love to have a posse to hang with in Vegas this year.

Are you going? Let me know!


* I do not, in any way, actually endorse blackmailing anyone. Please take it for the alliteration it was meant to provide, and nothing more.

Labels: , , ,

posted by Jeff Blankenburg, 9:36 AM | link | 1 comments |

JUXtapose Episode 2: ComponentOne Sapphire Interviews

Monday, November 05, 2007



JUXtapose - Episode 2: ComponentOne Sapphire Interviews
JUXtapose - Episode 2: ComponentOne Sapphire Interviews


Oh, and the timing is perfect...they just released the Alpha version of Sapphire today. Just register on their site, and download the installer!

http://labs.componentone.com/Sapphire/

Labels: , , , , ,

posted by Jeff Blankenburg, 12:03 PM | link | 0 comments |

Introducing JUXtapose

Friday, November 02, 2007


So I'm sure I'll be posting these everywhere, but I want my blog to at least be the starting place.

JUXtapose is the name of my new webcast series, and it will be primarily focused on the technologies I am most passionate about. This includes user interface technologies like Silverlight and WPF, as well as more general stuff like Javascript and CSS. It will also feature interviews from notable (and soon to be notable) developers in the field that have an opinion to lend on user experience.

The name JUXtapose comes from the subtitle: Jeff on User Experience.

Please leave comments, I'd love your initial thoughts on this, as well as recommendations and volunteerism for future shows.

Labels: , , , ,

posted by Jeff Blankenburg, 1:12 PM | link | 4 comments |

Central Ohio .NET Developer's Group Recap

Friday, October 26, 2007

I had an opportunity to speak at the October CONDG meeting last night, and had a great crowd. It was a great talk on Silverlight and some of the other cool things that Microsoft is up to, including Popfly, Surface, and Photosynth.

We also cleaned out the "swag closet," giving away a total of 16 items. This included some rubberized, roll-up keyboards (for typing in the bathtub), some 32MB flash drives, some 128MB flash drives, a few books, and a copy of Vista (congrats to Aaron Ponzani!).

Included in this post are links to the slide decks and demos that I used during the presentation.

Thanks to everyone that attended!

Silverlight 301 Deck & Demos

Innovative Microsoft Stuff Slide Deck

Labels: , , , , ,

posted by Jeff Blankenburg, 10:05 AM | link | 1 comments |

Silverlight 301 (and some other cool stuff)

Monday, October 22, 2007

I'm going to be talking on Thursday at the CONDG (Central Ohio .NET Developer's Group) meeting. I've been asked to speak on a higher level about Silverlight and the things you can REALLY do with it.

I'm going to be covering web service interactions, user controls, and event handling in Silverlight. In addition, we're going to be looking at some of the other cool stuff that we at Microsoft have been up to.

This includes: Popfly, Photosynth, SeaDragon, and even the new Surface. (No, we won't have an actual Surface device...at least NOT YET.)

I hope to see everyone there!

Labels: , , ,

posted by Jeff Blankenburg, 12:30 PM | link | 0 comments |

Adobe Illustrator to XAML

Wednesday, October 03, 2007

Some of you, my dear readers, have asked how I got over that magical step in my Silverlight Animation Tutorial. The step where I had an Adobe Illustrator file, and then, POOF!, I had the XAML to start working with it.

No, I didn't recreate the logo in Expression Blend. Mike Swanson created an AI->XAML Exporter. You will need:

* Adobe Illustrator CS2
(I don't know how they did it, but every trial version of this software on the web has disappeared. There used to be a 30 day trial...now you can only find Illustrator CS3. This is why I save all of my installation files.)

* Mike Swanson's Export Plug-in

* The rest of his instructions.

One quick thing to remember, however, is that there are a couple of quirks with the XAML you get. The syntax is good. No issues there. But it is creating XAML for WPF, not Silverlight. WPF has a much larger set of tags to work with, and as such, most WPF XAML may not be directly compatible with Silverlight.

Not in a "these are totally different" way, more in a "the opening and closing tags for WPF are different than Silverlight." WPF uses <window> as its top level tag, and Silverlight uses the <canvas> tag. Window is meaningless to Silverlight, because you don't have a window for it. It's only part of a web page. You can see this illustrated below:

Default code generated for a WPF application:
<Window
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     x:Class="UntitledApplication1.Window1"
     x:Name="Window"
     Title="Window1"
     Width="640" Height="480">
     <Grid x:Name="LayoutRoot"/>
</Window>


Default code generated for a Silverlight application:
<Canvas
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="640" Height="480"
Background="White"
x:Name="Page"
>
</Canvas>


So, in order to use the XAML that is generated by this tool in Silverlight, you're going to have to chop the "middle" of the XAML out and paste it into your new Silverlight app. Everything else should be the same. Ta-da!

Labels: , , , ,

posted by Jeff Blankenburg, 8:19 AM | link | 0 comments |

TUTORIAL: Creating A Simple Silverlight Animation

Monday, October 01, 2007

Silverlight has to be one of the easiest things I have ever worked with.

Last year, I was asked to put together a logo and site design for a new type of technology conference: CodeMash. (As a sidenote, registration just opened for the 2008 Codemash. For the price, it is by far one of the best conferences you'll attend this year.)

I designed the logo in Adobe Illustrator CS2, knowing that it would be used for print materials, the website, t-shirts, etc. It only made sense to create it using vector graphics. Little did I know at the time, it would also be the way that I turned that logo into an animation for CodeMash v2.0.0.8.

This post is meant to be a tutorial on what it really takes to create a simple Silverlight animation.

First, you are going to need to install some software (I am including links the newest stuff, but you should be able to do this with v1 of expression, and no Silverlight):
* Silverlight 1.1. Alpha
* Microsoft Expression Blend 2 September Preview (This version is good through June 1, 2008)

Once you've got those installed, you're also going to need some base XAML (eXtensible Application Markup Language) to work with. Download the CodeMash logo here. All this markup is at this point is the design. Just save this .txt file down, and we'll use it momentarily.

OK, now on to the tutorial:

1) Open Expression Blend 2, and create a new project.

2) Choose Silverlight Application (.NET)

3) By default, Page.xaml will be open. Choose the XAML view.

4) Cut and paste the contents of the logo.xaml file you downloaded earlier IN BETWEEN the <canvas> and </canvas> tags that are currently provided to you.

5) Flip back to the Design view, and you should now see the CodeMash logo on your canvas.

6) You're probably also noticing that the white canvas we started with isn't really big enough for our design. We should probably make that bigger as well. It needs to be 650px x 777px. We've got two options with this one. This first is just to edit the XAML directly. Take a look at that initial <canvas> tag we started with. It's got width and height properties, so we can just change the values. The second option is much better for those of you that don't want to edit your XAML directly. Click on the element named "Page" (that's our primary canvas) in the "Objects and Timeline" panel. Then, click on "Properties" in the top right. This shows you, much like Visual Studio, the Properties that are available to the element you've selected. Finally, you'll see the width and height properties in the list. You can type the values there, or you can use the innovative "slider" interface to get to the value you desire.

7) Take a look at the Objects and Timeline panel. You should see a well organized list of all of the elements that make up the logo. Gears, glasses, etc. Each one of these elements is defined in the XAML we imported. We are primarily going to be working in this panel the rest of the way.

8) Press F7 on your keyboard. This will take us into the "Animation Workspace." It's not any different from the "Design Workspace" (F6) we were in, except that the panels have been moved.
9) Expand the elements in the Objects and Timeline panel, and look for:
Page > Orange_Gear > Orange_Gear_Teeth. Click on that element once, highlighting it.

10) Under the "Objects and Timeline" panel header, there is a drop-down list with "(No Storyboard open)" as the selected value. Click the ">" button just to the right of that list. This will bring up the storyboard search dialog. Click the "+" symbol to create a new storyboard. Name your timeline/storyboard (it's named Timeline1 by default), and click "OK." Since we're gonna be animating the gears, I named my timeline "GearSpin."

11) You will now see that a timeline has appeared next to our list of elements. Each number (1, 2, 3, etc.) represents one second of time. We will use these times to "schedule" our animations. For those of you unfamiliar with animation software, we are going to be creating keyframes that will do most of the animation work for us. Basically, we define the states we want our elements to be in at certain keyframes, and the software figures out how to get it from Point A to Point B without any other instruction. Please also notice that your canvas now has a red line around it, and in the top right corner, now says, "Timeline recording is on." This means that all of our future actions will be recorded and animated. When we want to make a change that we don't want to be part of the animation, we need to make sure to turn recording off.

12) Make sure that the element "Orange_Gear_Teeth" is still selected. Just above where ZERO seconds is on the timeline, there is an icon with a green "+" in it. Click it. By clicking this, we are creating a keyframe at 0:00 of our animation. This means that it will start as soon as the application does. We could move this to 1 second if we wanted a 1 second delay before our animation began, but for this demo, we want it to start at the beginning.

13) Next, we need to create a new place for these gears to be. So let's say we want to have them rotate 90 degrees in 1 second. Drag the yellow timeline indicator to one second. Click the "+" to set another Keyframe at 1 second. In the "Properties" tab in the top right of Expression Blend, find the "Transform" section, and click the "Rotate" tab inside there. You will see that the current Angle is set to 0 degrees. Let's change that to 90 degrees. You can either click and drag the box to the right, until it says 90, or you can just click on the box, which will allow you to type 90.

14) Whoa! You may have noticed that your gear teeth have derailed from their hub. That's because we didn't define the center of those objects appropriately. Press CTRL + z on your keyboard, to undo the change you just made. Also, because we don't want to animate moving the center of these objects, we need to turn off recording. You can do this by clicking on the red circle in the top right corner of the canvas.

15) Because you have highlighted the "Gear_Orange_Teeth" layer, you should see a blue box surrounding those elements, but probably a bit bigger than just those elements need. You should also see a white dot that indicates where the center of that entire box is. We need to move that. Click on it and drag it to the blue center of the orange gear. That's the point we want our teeth to rotate around, right? To be more exact, I recommend zooming in and placing your center point that way.

16) Once you're confident in your center point, turn recording back on, modify that angle again, changing it to 90 degrees. Now you can click the "PLAY" button (it's right above the timeline) to see your orange gear spin.

17) We've got one other thing to take care of to make this look great. We don't want to have the gears stop after 1 second. We want them to continue spinning forever. This is a simple change. We had selected Orange_Gear_Teeth from the timeline earlier, and now we need to expand it. Inside it, you will see a RenderTransform element. This was created when we changed that rotation angle. Expand it all the way, and you will see an "Angle" element. Right-clicking on this will give you the option to "Edit Repeat Count." We can set this to 1, 2, 100, etc. There's also an "infinity" option. Choose that, and our gears will spin forever.


18) Now, we need to animate the other two gears. We are going to follow the same steps for the Blue and Green Gears. So take steps 9-17, rinse, lather, repeat. The only difference for the other two gears is that they rotate in the other direction. So instead of 90 degrees, they will be set to -90 degrees.
19) You should now have a working Silverlight application, that has the gears spinning. Press F5 to run your project!

Labels: , , , ,

posted by Jeff Blankenburg, 2:32 PM | link | 4 comments |

--> This Guy <--

Tuesday, September 11, 2007

So, from time to time, I have been known to use the phrase "This Guy" while pointing at myself with my thumbs. Sure, it's tired. Sure, it's obnoxious. But it conveys my point effectively, and I use it only in the most appropriate instances:

"Who has two thumbs and loves him some Silverlight?"

--> THIS GUY <--

And that's the point of this post. I think this saying is worn out because people haven't had an effective way to communicate this electronically. Now you do. Go out into the world and use it, with discretion.

BTW, I cannot take credit for this syntax. The credit belongs to another brilliant blog.

Who loves reading Kiss Me Suzy?

--> This guy <--

Labels: ,

posted by Jeff Blankenburg, 6:57 PM | link | 2 comments |

Basking In The Moonlight

Wednesday, September 05, 2007

While I was at Mix 07 as a guest of Microsoft, I had an opportunity to witness some amazing products that were coming in the near future. The one I found the most impressive was a technology called Silverlight. The "canned" answer to what Silverlight is, is: Microsoft® Silverlight™ is a cross-browser, cross-platform plug-in for delivering the next generation of .NET based media experiences and rich interactive applications for the Web.

For the three of you that I haven't told about it yet, here's some cool examples to see what's capable:

Tafiti - Silverlight Search Engine based on Live Search

Halo 3 Trailers

Major League Baseball Video Streaming

Anyways, the point of this post is to announce that Silverlight 1.0 has been released! You can go to http://silverlight.net/GetStarted/ now to download the final release of the runtime and development tools.

In addition, Microsoft has also announced a partnership with Novell, which will be building a 100% compatible Silverlight runtime implementation called "Moonlight".

Moonlight will run on all Linux distributions, and support FireFox, Konqueror, and Opera browsers. Moonlight will support both the JavaScript programming model available in Silverlight 1.0, as well as the full .NET programming model we will enable in Silverlight 1.1.

UPDATE: Here's plenty more information on Moonlight.

This is an exciting day for user experience. If you want help getting started on your first project, or just want to tell me about the cool way you're using Silverlight, drop me a line!

For all the nitty gritty details about this release, I don't think I can say it as well as Scott Guthrie, so check out his blog post on this as well.

Labels: , , ,

posted by Jeff Blankenburg, 8:56 AM | link | 0 comments |

Silverlight Presentation

Monday, August 27, 2007

Just a reminder to all of you in the Southfield/Ann Arbor/Detroit area...I will be presenting the Silverlight DevCares event on Wednesday, August 29.

http://www.devcares.com to sign up.

See ya there.

Labels: , ,

posted by Jeff Blankenburg, 9:22 AM | link | 0 comments |

Free Web Hosting For All

Saturday, August 25, 2007

I just got an inside tip that Verio is offering free MS web hosting through 2010. So, if you've been meaning to get around to building the next killer app, here's your chance to do it for free.

They even support Silverlight, so if you've been meaning to try it out, GET TO IT!
I believe they are Windows Server 2003, with IIS 6. You don't even need a credit card.

All you have to do is call Verio’s 800-932-7483 to receive your free website. This offer is unfortunately not available online. Please pass it along.

Labels: , ,

posted by Jeff Blankenburg, 8:56 AM | link | 2 comments |

Mix '08...won't it be great?

Friday, June 01, 2007

They've already announced the dates for the Mix '08 conference. I'm really hoping to get an opportunity to go again. I'm still revelling in the knowledge and experience of the trip.

March 5-7, 2008. Venetial Hotel. Be there or be less than desirable.

Labels: , , ,

posted by Jeff Blankenburg, 4:01 PM | link | 0 comments |

Day 1: Holy Cow.

Monday, April 30, 2007

So it's been hyped for the past few weeks that we were going to see many new things announced by Microsoft this morning. The hype didn't keep up with reality.

It was WAY better than sold.

THe biggest highlight of this conference is the combination of Silverlight with the .NET framework.

We can actually write C# code to function like you would normally expect Javascript to do.

We can create vector based animations to run in a cross-browser, cross platform environment, with all of the instructions stored in XAML.

Designers can completely control the look and actions of these elements in a graphical interface, but that design is then translated down to XAML, which can be edited, updated, etc as a file on the server. This allows the designer to control the looks, and the developer to control the functionality.

Two demos during the keynote were flooring, however.

First, the CEO from a company named Metaliq demoed a new AJAX/Silverlight/.NET application they call Top Banana. It is basically a content editing application, all within a browser. The URL is http://silverlight.metaliq.com/topbanana
It appears they have taken their demo down, but as soon as I can get access to it again. I will post it. It was truly unbelieveable.

The other struck close to home. I'm a huge baseball fan. Mondo big. And having grown up in Cleveland, I've been forced to suffer with the Indians my entire life. THe C-something-something from MLB.oom was here demoing their new MLB.TV application. It acted as I expected. Showed every possible statistic available in an interface that also shows the live games streamed over the internet. All great, all what I would expect. It include a feature that allowed you to add your favorite players (think fantasy baseball) and it would alert you every time your player did something in any of the games. It would also serve up the specific video clip of that notable performance. (On a sidenote, thsi guy said that they generate 10 DVDs worth of data with every pitch of every game. That seems like a little bit. :))

Anyways, even the fantasy player list wasn't the coolest part of this demo. Oh no. He then pulled out his cell phone, and showed us a Silverlight application running there. It showed stats, game scores, even live score updates, and runners on base. Think about the graphics that show up during a TV broadcast. Minus the actual game video. Well, with Silverlight, it appears they are going to be successful in streaming actually live video to your phone, and remember that fantasy player list, statistics, and video feeds? That was all demonstrated as well.

Man, this has been amazing thus far. Thanks again to Quick Solutions for sending me here.

Labels: , , , ,

posted by Jeff Blankenburg, 6:34 PM | link | 1 comments |

Search

My Sponsor


My Badges



Follow Jeff Blankenburg on Twitter