Thursday Night

Paul Betts’s personal website / blog / what-have-you

Archive for the ‘WPF / Silverlight’ Category

Using Blend Sample data at Design time and real data at Runtime

Sample Data is Awesome

Here’s a clever trick that I found out the other day – one of Blend 3’s best features is Sample Data, which allows you to generate basic data structures in Blend, create sample arrays of them, and mock up UIs so that your DataTemplates actually show something useful. This is a huge improvement over Blend 2 and VS, where important parts of your UI would basically be invisible until you actually could build the project and populate it with real data.

Keep Sample Data all the time

One thing I always struggled with though is, that you always had to switch the binding back and forth between the sample data and the real data – even though Blend has a “Only enable sample data at design time” feature, you could still only bind the data to one place. But there’s a clever hack to get around this, you can see me applying it in this Github commit.

Basically, say you had a Listbox:

<grid x:Name="LayoutRoot" DataContext="{Binding ViewModel, ElementName=Window}">
    <!– Sample Version
    <ListBox ItemsSource="{Binding Path=Data, Source={StaticResource SampleData}}" />

     –>

    <listbox ItemsSource="{Binding Path=TheData}" />
</grid>

Here’s the trick – Blend doesn’t let you redirect the binding at Design time, but it will let you redirect the context. So all you have to do, is group the ItemsControl in a meaningless container, then rig the DataContext; d:DataContext is what Blend will use at Design time and will be ignored by WPF / Silverlight.

<grid x:Name="LayoutRoot" DataContext="{Binding ViewModel, ElementName=Window}">
    <border DataContext="{Binding Path=TheData}" d:DataContext="{Binding Path=Data, Source={StaticResource SampleData}">
        <listbox ItemsSource="{Binding}" />
    </border>
</grid>

Et, Voila!

Now, whenever we edit in Blend we see our sample data so we can edit the UI, then when we run it, we’ll use the live data instead.

Written by Paul Betts

February 2nd, 2010 at 8:00 am

Posted in WPF / Silverlight

Patching Silverlight Media Framework to work with MP4/WMV files

2 comments

For a project I’m working on at work, I had a need for an easy to embed video control into my Silverlight UI – previously I had been using some code hacked out of an Expression Encoder template, but it had a few bugs and didn’t look very nice. I was quite happy then, when Microsoft released the Silverlight Media Framework during PDC09. It’s got a nice UI, it’s easily themeable and embeddable, and a fairly complete player framework (supports things like timeline markers, etc).

Much to my dismay however, I discovered that it was only compatible with IIS Smooth Streaming files, not the standard MP4 files that I had been using. However, they also ship the source, so I have a chance to do some hacking and turns out, it was pretty easy to make this work properly.

diff –git a/Microsoft.SilverlightMediaFramework.Player/CoreSmoothStreamingMediaElement.cs b/Microsoft.SilverlightMediaFramework.Player/CoreSmoothStreamingMediaElement.cs
index f642d2c..fadd5e6 100755
— a/Microsoft.SilverlightMediaFramework.Player/CoreSmoothStreamingMediaElement.cs
+++ b/Microsoft.SilverlightMediaFramework.Player/CoreSmoothStreamingMediaElement.cs
@@ -725,7 +725,7 @@ namespace Microsoft.SilverlightMediaFramework.Player
                        maxSelectedStreamBitrate = 0;
 
                        // get video stream
-                       var streamResult = (from stream in SelectedStreams
+                       var streamResult = (from stream in SelectedStreams ?? Enumerable.Empty< StreamInfo > ()
                                                                where stream.Name == "video"
                                                                select stream).SingleOrDefault();

So, if you don’t grok what this is saying, here’s what it means – download the source, open the Microsoft.SilverlightMediaFramework.Player/CoreSmoothStreamingMediaElement.cs file, then go to line 728 or so, and replace "from stream in SelectedStreams" with "from stream in SelectedStreams ?? Enumerable.Empty<StreamInfo>()". Then, rebuild the project (remember, you have to download Microsoft.Web.Media.SmoothStreaming.dll from here before you’ll be able to build the project.

Once you have the patched SMF, you should be able to play any file by doing something like:

void setPlayerToUrl(string url)
{
    var cme = new CoreSmoothStreamingMediaElement() {
    Source = new Uri(url),
    };
    Player.MediaElement = cme;
}

Written by Paul Betts

November 22nd, 2009 at 4:29 pm

Posted in WPF / Silverlight

WPF WebBrowser blank? Check your Airspace!

WPF’s WebBrowser control (and in fact, all native controls, like the Ink controls), have a pretty subtle "gotcha" that made me spend a decent amount of time pulling my hair out. The control would render as all white like it hadn’t loaded the page, yet you can still see Tooltips from the web site as you mouse over the control! Clicking on links still works, scrollbars show up, yet the control is all white! What gives?!

My problem has to do with Airspace; WPF completely discards the concepts that Win32 and WinForms have used to handle UI rendering in the past – all controls in WPF are "Windowless controls"; there is only one HWND allocated to the entire window, whereas Win32 windows typically have many, many HWNDs allocated (one per control). It is this "impedance mismatch" that causes a lot of tricky issues, especially with keyboard/input focus. My Window had the "AllowsTransparency" bool set, so it was being created as a layered window.

The way I solved this in my app was simply to set the AllowsTransparency property of my Window to "false". I suggested that WebBrowser should throw an Exception when it encounters this situation, and the WPF team filed a bug against it for .NET 4.0 so hopefully, this specific gotcha won’t continue into the future.

Written by Paul Betts

November 20th, 2009 at 8:28 pm