Friday, October 26, 2007

The great thing about hosting Silverlight plugins on your web page is that you can load it with any XAML (not just the popular use of video as I've shown in my recent posts). For example, you can start drawing on this grid...

...and this is made possible due to the powerful XAML InkPresenter element. By adding this markup/code to a web page (provided that the silverlight.js file is referenced like before, see my earlier post on that)...

<script id="inkXaml" type="text/xaml"><?xml version="1.0"?>
    <Canvas xmlns=
"http://schemas.microsoft.com/client/2007"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     Loaded="onXamlLoaded">
        <Image Source="images/gridpaper.png" Width="300" Height="221"/>
        <InkPresenter x:Name=
"inkPresenter"
         Background="transparent" Width="300" Height="221"
         MouseLeftButtonDown=
"onInkPresenterMouseDown"
         MouseMove=
"onInkPresenterMouseMove"
         MouseLeftButtonUp=
"onInkPresenterMouseUp"/>
    </Canvas>
</script>
<
div id="inkHost" style="width: 300px; height: 221px">
<
script type=text/javascript>

    Silverlight.createObjectEx({
        source:
"#inkXaml",
        parentElement: document.getElementById(
"inkHost"),
        id:
"inkPlugin",
        properties: {
            width:
"100%",
            height:
"100%",
            version:
"1.0",
            inplaceInstallPrompt:
true,
            background:
"white",
            isWindowless:
false
        },
        events: {}
    });

    
var plugin;
    
var inkPresenter;
    
var stroke = null;

    
function onXamlLoaded(sender, args)
    {
         plugin = document.getElementById(
"inkPlugin");
         inkPresenter = sender.findname(
"inkPresenter");
    }

    
function onInkPresenterMouseDown(sender, eventArgs)
    {
        inkPresenter.CaptureMouse();
        stroke = plugin.content.createFromXaml(
"<Stroke/>");
        stroke.StylusPoints.AddStylusPoints(
            eventArgs.GetStylusPoints(inkPresenter));
        stroke.DrawingAttributes.Color =
"#FF000DDD";
        stroke.DrawingAttributes.Width = 1;
        stroke.DrawingAttributes.Height = 1;
        inkPresenter.Strokes.Add(stroke);
    }

    
function onInkPresenterMouseMove(sender, eventArgs)
    {
        
if(stroke != null)
           stroke.StylusPoints.AddStylusPoints(eventArgs.GetStylusPoints(inkPresenter));
    }

    
function onInkPresenterMouseUp(sender, eventArgs)
    {
       stroke =
null;
    }
</script>
</
div>

...you have made it possibility for your users to make handwritten notes on your page. The XAML is fairly simple with the background (grid) behind the InkPresenter, and the scripts are used to create new Stroke elements for each mouse gesture (down, moves, up).

There are many things you can do with this, and for a more extensive sample, check out the Silverlight Ink SDK Sample. For example, as the ink (strokes) is basically XAML, it's definitely possible to save in on the server side (why not in a database). As the strokes are created on the client, this would require some functionality to upload the ink, probably implemented using scripts that communicate with the web server (a.k.a. AJAX). This means that you could create everything from a simple inking guestbook to capturing ink feedback on a CAD drawing (note that the grid above is an image file). I haven't seen much of this in real-world applications yet, but there is a sample called Journal Note Converter Sample which allows you to convert a Microsoft Journal note to a complete Silverlight application that allow further inking.

posted on Friday, October 26, 2007 10:16:17 PM (E. South America Standard Time, UTC-03:00)  by Chris  #    Comments [0]
 Thursday, October 25, 2007

I've realized that I made a mistake in my previous post about the simple video player. The problem with my video player was that it started loading the video when the web page was loaded. That is something users with low bandwidth are not so happy about (especially when the video is about 10 MB, as in this case). If you change the XAML to contain a play button like this...

<Canvas xmlns="http://schemas.microsoft.com/client/2007"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <
MediaElement x:Name="Video" Width="420" Height="236"
     MouseLeftButtonDown="onVideoMouseDown" MediaEnded="onVideoMediaEnded"/>
    <
Canvas x:Name="PlayButton" Canvas.Left="185" Canvas.Top="93"
     Width="50" Height="50" MouseLeftButtonDown="onButtonMouseDown">
        <
Rectangle Fill="#3F000000" Stroke="#FF000000" StrokeThickness="2"
         RadiusX="10" RadiusY="10" Width="50" Height="50"/>
        <
Path Fill="#FF000000" Stretch="Fill" Stroke="#FFD10000" StrokeThickness="0"
         Width="24" Height="34" Canvas.Left="15"
         Canvas.Top="8" Data="M224,184 L224,208 240,196.37082 z"/>
    </
Canvas>
</
Canvas>

...and add the following script...

function onButtonMouseDown(sender, eventArgs)
{
    sender.findName(
"PlayButton").Visibility="Collapsed";
    sender.findName(
"Video").Source="http://www.businessanyplace.net/chris/slintro.wmv";
}

...you will be much better off because the only thing that is loaded initially is the XAML. When the play button is clicked, it will disappear, and the video starts loading and playing. The play/pause functionality is still the same as before. I have updated my previous post now, so I hope all you with lower bandwidth will be happy about that.

posted on Thursday, October 25, 2007 2:44:22 PM (E. South America Standard Time, UTC-03:00)  by Chris  #    Comments [0]
 Tuesday, October 23, 2007

One of the coolest Silverlight features is the ease with which you can use media on your web site. There are numerous quickstarts, tutorials, videos, and webcasts to show you how easy you can build your own video player. The power of Silverlight can be released with a little XAML, and here is one of the simplest XAML video players around:

<MediaElement xmlns="http://schemas.microsoft.com/client/2007"
    Source="http://www.businessanyplace.net/chris/slintro.wmv"/>

You need a Silverlight control on your page to make it work, but it works. If you have .NET Framework 3.0 installed, you can change the namespace to...

<MediaElement xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    Source="http://www.businessanyplace.net/chris/slintro.wmv"/>

...place it in a file (e.g. videoplayer.xaml), and then you can open it file in Internet Explorer. That's already cool, but let's get back to how to use it with Silverlight.

In a minimal approach, there is only one file that you need to put up on your web site, it's called silverlight.js and comes with the Silverlight SDK. It basically takes care of creating the actual Silverlight plugin on the web page (with support for PC or Mac and the most common browsers). Put this file in a script directory (e.g. "js" below you web page root).

With that file in place, you are ready to create your first web page that include video playback, and it can look like this...

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<
head>
    <title>Video Player</title>    
    
<script type="text/javascript" src="js/Silverlight.js"></script>
</
head>
<
body>
<
p>Here's some text, and here comes the video...</p>
<
script type="text/xaml" id="firstXaml"><?xml version="1.0"?>
    <MediaElement xmlns=
"http://schemas.microsoft.com/client/2007"
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Source="http://www.businessanyplace.net/chris/slintro.wmv" x:Name="Video"
    AutoPlay=
"false" MouseLeftButtonDown="onVideoMouseDown"
    MediaEnded="onVideoMediaEnded"/>
</script>
<
div style="width: 208; height: 160;" id="firstHost">
<
script type="text/javascript">
    Silverlight.createObjectEx({
        source:
"#firstXaml",
        parentElement: document.getElementById(
"firstHost"),
        id:
"firstPlugIn",
        properties: {
            width:
"100%",
            height:
"100%",
            version:
"1.0",
            inplaceInstallPrompt:
true,
            background:
"white",
            isWindowless:
false
        },
        events: {}
    });

    
function onVideoMouseDown(sender, eventArgs)
    {
        
if(sender.CurrentState != "Playing")
            sender.Play();
        
else
            sender.Pause();
        }

    
function onVideoMediaEnded(sender, eventArgs)
    {
        sender.stop();
    }
</script>
</
div>
<
p>...and some more text!</p>
</
body>
</
html>

...and note how I reference the script file mentioned above. The actual XAML is located in the firstXaml script tag, and you can see that I've added some attributes like a name (required by the event functions), event handlers, etc. Then I just call the Silverlight.createObjectEx method with the name of the XAML (script) tag, the script (div) host, and the name of this instance of the plugin. I have also added two methods to support the video playback by allowing the click of the mouse on the video player to play and pause, and to automatic rewind of the video when it's done. Note that there's nothing preventing me from adding various videos on the same page as long as I give all parts unique names.

Using this approach I have included the cool intro video from the REMIX 2007 event (click below to play/pause the video).

posted on Tuesday, October 23, 2007 10:40:46 PM (E. South America Standard Time, UTC-03:00)  by Chris  #    Comments [0]
 Thursday, October 18, 2007

Even if the Silverlight Downloader is fairly tolerant when it comes to handling unsuccessful downloads of files from the server, it can be inefficient to use that tolerance. As an example, I was playing around with Michael Schwarz's excellent Surface sample (source code) and wanted it to handle an arbitrary number of pictures. I therefore created a general purpose method that uses the BrowserHttpWebRequest (only link I could find) from the System.Windows.Browser.Net namespace, and it looks like this...

public static bool CheckUri(Uri uri)
{
    
bool exists = false;

    
try
    {
        
HttpWebRequest request = (HttpWebRequest) new BrowserHttpWebRequest(uri);
        request.Credentials =
new NetworkCredential("Username", "P@ssw0rd");
        request.PreAuthenticate =
true;
        
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        request.Abort();

        
// Success?
        if(response.StatusCode == HttpStatusCode.OK)
            exists =
true;
        response.GetResponseStream().Close();
    }
    
catch(WebException we)
    {
        exists =
false;
    }
    
catch(Exception ex)
    {
        exists =
false;
    }
    
return exists;
}

...and with this placed in a helper class (e.g. NetHelper), the check can be made with code similar to...

for(int i = 1; i < 100; i++)
{
    
if(NetHelper.CheckUri(new Uri(HtmlPage.DocumentUri, "photo" + i.ToString("00") + ".jpg")))
        
// File exists, so get it using Downloader
    else
        break;
}

...assuming that the photos are named in sequence "photo01.jpg", "photo02.jpg", and so on. The loop will download photos until one in the sequence is missing.

Note that the CheckUri method can be used to check connectivity in general. Of course, you can check that you have a network connection using the InternetGetConnectedState Windows API or even that a specific domain exist with Dns.GetHostEntry, but if you want to check for a specific file (e.g. the .asmx file of an XML Web Service), the CheckUri method is very useful.

BTW, a tip is to set the inplaceInstallPrompt parameter to true to speed up your users installation of the Silverlight plugin.

 

posted on Thursday, October 18, 2007 8:36:27 PM (E. South America Standard Time, UTC-03:00)  by Chris  #    Comments [0]
 Wednesday, October 17, 2007

User Experience (UX) on the web and on Windows clients is moving forward! We have moved from the basic (HTML) to the second wave (DHTML/AJAX/etc), and even if many (the games industry is always ahead) have already created a better UX (mostly with Flash), much is still to be done. I believe that one important reason is that Flash requires the traditional site developers to learn both a new tool and programming language/model. And even if the first version of Silverlight build on well-spread JavaScript with the addition of XAML, it's with Silverlight 1.1 (now in Alpha since September) that things are getting interesting. The reason is that the Silverlight applications are now driven by the managed code that we have learned to love (and sometimes hate). The new thing to learn is WPF and XAML, but with excellent books like Applications = Code + Markup and sites like WindowsClient, I'm fine, and with tools like SWF to Xaml I can even reuse the cool stuff all those designers already created. If you want to get started right away, check out this great blog post by David Crow.

If you need to be more motivated, you should check out all the great Silverlight demos out there. Two great sources are the blog posts by Tim Sneath and Mikael Schwarz, and my personal favorites at the moment are the site on Presidential Election 2008 demo and the RIA Eurojob demo built with GOA which allows you to code as in WinForms and then run in Silverlight or Flash.

Don't you just want to build applications like the screenshot on the right (click on image for more info)?

posted on Wednesday, October 17, 2007 4:56:27 PM (E. South America Standard Time, UTC-03:00)  by Chris  #    Comments [0]
 Tuesday, October 16, 2007

So, after my post on waiting for Silverlight for Devices, I spent last night and much of today finding a way to render XAML on a web server. You can see the result in the article Silverlight on Devices, and of course the code is also included.

As expected, there are a lot of the good stuff that you miss out on using this approach (interactivity, animations, etc), but it serves the purpose of moving the design elements of your application to the new user interface platform (XAML, WPF, etc). When the technology is available on the device, the work done can be migrated to the mobile application.

In the article's sample I only render static XAML on the server, as I couldn't get the data binding to work (anyone?), but in most situations this shouldn't be a problem as you do the rendering on the server anyway.

posted on Tuesday, October 16, 2007 4:44:01 PM (E. South America Standard Time, UTC-03:00)  by Chris  #    Comments [0]
 Monday, October 15, 2007

Ever since Mike Zintel's post WPF/e and the .NET Compact Framework on my 40th birthday more than two years ago, I have been waiting. I think he was right then, and I still think he is right. We need an implementation that focuses on the user interface and that allows for both online and offline. My only concern was why it was taking so long, and finally my hopes were out...

...and THEN, Robert Unoki made me green with envy when he posted on his cool work with Silverlight and Compact Framework. A bit later the video with Scott Holden appeared, and my hopes were on max again. But that was almost six months ago, and now I'm getting really inpatient. When you look at the great developer overview of the current Alpha build of Silverlight, Compact Framework isn't even on the "map" (neither is XBOX/XNA).

Even if I mostly build Enterprise applications, I want to build UXs like that (yes, Mike Zintel was right again on his theory that somewhere inside we all get into this business hoping to write video games ;-))

So, what can I do while waiting? Well, I remember that when I didn't have GDI+ on the device, I would create on-the-fly charts on a Web server that download them directly to my WinForms apps on the device. It had its drawbacks, but served my purpose. What if I could do the same with XAML on the server? I'll take a look at that soon...

posted on Monday, October 15, 2007 10:43:53 PM (E. South America Standard Time, UTC-03:00)  by Chris  #    Comments [1]