WPF theme generation with Thematic–install via ClickOnce from CodePlex

19. January 2011

My WPF theme creation tool thematic is now available for install directly from codeplex. I’m calling it beta 1 and it still has a few rough edges. Briefly here is the problem it tries to solve:

The Problem: Creating a custom theme for your WPF application, such as selecting colors and creating custom control templates and styles can be a long and complicated process, especially for smaller teams without dedicated design skills.

How Thematic Helps: Thematic helps you to fast-track this by letting you choose from a number of groups of custom control templates and styles, and then choose colors that match your company, project or campaign. Then you can generate this out as a running Visual Studio solution, with the theme and style information factored out nicely into a separate DLL.

The Process: Choose some colors, choose a set of control templates, click Generate.

I created a screen-cast a little while back that shows how to do this with a slightly older build of thematic.

thematic_video2

Virtualizing TreeView for Silverlight, with Diagrams

13. January 2011

*Note* If you’re getting a sense of deja vu reading this, it’s because I posed this about 6 months ago, but it was lost when I was migrating it between blog back-ends. I’ve restored it now in it’s full…errr…..glory.

For large hierarchies the TreeView in the Silverlight tool-kit suffers some performance problems, because the elements (once loaded and expanded, such that they could be seen by the user if they scrolled the scroll-bar) aren’t virtualized as aggressively as they could be. The for example the hierarchy shown below: If Child Node 4 is expanded, pushing Child Node 5 outside the limits of the view port of the TreeView then Node 5, as well as any other children of Node 4 that aren’t directly visible, _could_ be virtualized but currently aren’t by the Silverlight Treeview. When the number of invisible-but-loaded nodes is small the performance impact is negligible, but if Node 4 (in the example below) had 10,000 children, each with a complex data template applied to them the performance impact expanding the tree can be quite noticeable.

treeview1

One approach to get around this is to recognize that a TreeView is just a List with indentation and expand/collapse semantics. By flattening your object hierarchy with an appropriate wrapper you can use the virtualization that is built into the ListBox, which happily does virtualize items that have disappeared off the top or the bottom of the list, by virtue of its use of the VirtualizingStackPanel that was added in Silverlight 3. http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel(VS.95).aspx

The sample provided does just that with two classes TreeViewModel<T> and NodeViewModel<T>. TreeViewModel<T> contains a Nodes collection, an ObservableCollection of NodeViewModel<T> which the list is bound to. The visibility of the expand/collapse arrow is bound to the presence of children. When a NodeViewModel<T> is expanded it calls back to the TreeViewModel<T> to tell the TreeViewModel to create a new set of NodeViewModels based on the children of the node being expanded, and to insert them directly after node being expanded in the current list of nodes. When the TreeViewModel makes new nodes it increments the indentation property, which is used to drive how far in the node is rendered when it is shown. When a NodeViewModel<T> is collapsed it again calls the TreeViewModel<T> and basically tells it to throw away all the nodes that come after me in the Nodes collection, until you reach one that has the same indentation as me (or you reach the end of the list), at which point the TreeViewModel will know that it has removed all the children of the item that was collapsed.

treeview2

The sample provided is not a complete drop-in replacement for the TreeView control in the Silverlight toolkit. For one thing some of the expand/collapse semantics are a little different to a standard TreeView. For example if all the nodes in the tree are fully expanded, and the root node is collapsed and then re-expanded then the standard tree-view behaviour is for the tree to look the same as before the root node was collapsed, however this tree will only show the direct children of the root node after the root node is collapsed and then re-expanded, regardless of the state of the tree before. This is a side-effect of the way this implementation creates and destroys NodeViewModel<T> instances when a node is collapsed/expanded. When a NodeViewModel<T> is removed from the list of nodes the fact that it was previously expanded is lost. This could be changed by keeping instances of removed nodes around, but would complicate the expand/collapse methods in TreeViewModel<T>. Also some other TreeView standard keyboard short-cuts are missing (for example right arrow to expand a node, and left arrow to contract it) are not wired up. Also it is likely that this technique will become obsolete at some point when the TreeView in the Silverlight Toolkit catches up with the WPF one and implements this trick for itself.

Download Code

I just Upgraded my WPF application from .NET 3.5 to .NET 4 and Now My Images Look Terrible–A Visual Guide to the BitmapScalingMode property.

1. December 2010

Although this has been mentioned in other places already, I thought it was worth calling this out specifically as a change from .NET 3.5 to .NET 4. With the release of .NET 4 Microsoft chose to change the default RenderOptions.BitmapScalingMode value from HighQuality to LowQuality. In many other areas the API changes when moving to .NET 4 were ‘opt-in’ so this was a little out-of-the-ordinary.

Below is a visual guide to the different types of image scaling modes in WPF v4, along with their names (although as Steve points out in the comments below there are really only 3 options since HighQuality is an alias for Fant, and LowQuality is an alias for Linear).

BitmapScalingModes

This image is 2 x larger than normal, with no interpolation applied during the resize, so it exaggerates the differences between the different scaling modes. How nice an image will look when a particular scaling mode is applied depends largely on the image, so I’ve included the code below. You can plug in an image of your choosing and see how the different scaling modes apply to it.

<Window x:Class="DotNet4ImageScalingMode.MainWindow"
        xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Margin="5">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
       
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
       
        <Image Source="winlogo.png" />
        <Image Source="winlogo.png" RenderOptions.BitmapScalingMode="HighQuality" Grid.Column="1" />
        <Image Source="winlogo.png" RenderOptions.BitmapScalingMode="LowQuality" Grid.Column="2" />
        <Image Source="winlogo.png" RenderOptions.BitmapScalingMode="Fant" Grid.Column="0" Grid.Row="2" />
        <Image Source="winlogo.png" RenderOptions.BitmapScalingMode="Linear" Grid.Column="1" Grid.Row="2" />
        <Image Source="winlogo.png" RenderOptions.BitmapScalingMode="NearestNeighbor" Grid.Column="2" Grid.Row="2" />

        <TextBlock Text="Default" Grid.Row="1" />
        <TextBlock Text="HighQuality" Grid.Row="1" Grid.Column="1" />
        <TextBlock Text="LowQuality" Grid.Row="1" Grid.Column="2" />
        <TextBlock Text="Fant" Grid.Row="3" Grid.Column="0" />
        <TextBlock Text="Linear" Grid.Row="3" Grid.Column="1" />
        <TextBlock Text="NearestNeighbor" Grid.Row="3" Grid.Column="2" />
    </Grid>
</Window>

Introducing theMatic–WPF Theme Generation Tool

3. November 2010

Doing a custom control theme in WPF is no small undertaking. theMatic (currently very-much-in-alpha) hopes to take some of that pain away, especially for smaller teams that don’t have a dedicated designer, or for quick apps that you still want to give that ‘custom’ touch.

The vision is that you choose a set of control templates (which I collectively refer to as a design), some typography, and a number of colors that make up your theme: colors for control chrome, colors for branding, colors for window foreground text and background. ThemeMatic gives you a live preview of these changes as you make them. Then when you’re done you click ‘Generate’ and out pops a 'theme' assembly that contains all the XAML that describes your theme. You reference this from your main application, and you’re done.

TheMatic is still in definitely alpha – the whole generate process is not done yet, and the three sets of control templates: Simple Styles, JetPack and Cosmopolitan have varying levels of support for the theme colors. It’s a work in progress, but I wanted to give everyone a preview to get some feedback. You can see it in action in this video:

ThemeMatic Preview from Joseph Cooney on Vimeo.

You can download the code from codeplex http://thematic.codeplex.com/ . In time I’d like to add support for more designs (from the WPF themes project), and further refine the current ones (they need a lot of work), but I’d love to know what additional features people would like to see.

Thanks to Scott Barnes for his feedback on how this app should work. Please leave comments here or on the codeplex site if you want to make any suggestions.

Chromatic Aberration Effect with WPF, HLSL, and Lena

19. October 2010

Chromatic aberration can be intentionally added as an artistic effect to production video and design. I have wanted to create a pixel shader effect to do this for some time. When I eventually sat down with Walt Ritscher’s Shazzam shader-effect tool the code I came up with was so simple I was disappointed I’d put off writing it for so long.

ChromaticAberrationWPFLike all effects this will work with controls and UI elements, images and video. You set the R, G and B offsets as ‘points' (so they have an X and Y offset). The RGB offsets can be animated (they’re dependency properties after all). Small offset values tend to look best.

You can download the source and sample application here: LearnWPF.ChromaticAberration.zip (112.46 kb)

LearnWPF, reloaded

5. October 2010

After a long hiatus LearnWPF is back on-line. Hopefully with much less spam. I've got some interesting posts scheduled for the next few weeks.

4 Free WPF Utilities I Use Every Day, that come with source!

1. March 2010

Here are 4 WPF utilities I use almost daily, that also have the excellent property of coming with source-code included.

Kaxaml icon Kaxaml Kaxaml is a great tool for quick experimentation with snippets of XAML. The editor has intellisense, and the app itself is gorgeous to look at. Written By Robert Ingebretsen you can download the source from codeplex.
shazzam icon Shazzam

 

Based on the code for Kaxaml this is a nifty app for experimenting and developing pixel shaders, especially for inclusion in WPF applications. It compiles the shaders, builds C#/VB.NET "wrappers" and auto-generates a GUI for editing the shader properties inside of Shazzam (so you can 'twiddle the knobs' and see what the effect on the shader is). Developed by Walt Ritscher it can also be downloaded from codeplex.

snoop icon Snoop

 

Think "firebug for WPF" - Snoop is my favourite application for viewing, editing and inspecting the visual tree of WPF applications. From its irreverent icon down to the many nice little touches in the UI, it is a great app, and I find myself turning to it, usually to get a better understanding of my OWN code rather than anyone elses. Originally written by Peter Blois it is now also hosted on Codeplex.

 

inkscape logo Inkscape Inkscape is an open-source vector graphics editor, primarily targeting SVG but which in the last couple of versions added support for XAML. I enjoy using the inkscape editor more than I like Expression Design, although I think Expression Design's XAML output options are better than inkscape. Inkscape is none-the-less a useful tool, especially when working with "raw materials" that aren't in XAML format. You can download the source form sourceforge.

Adding Simeltaneous Video Recording + Playback to WPFMediaKit's VideoCaptureElement

8. January 2010

When it comes to awesome WPF + DirectX video hacks it's Jeremiah Morrill's world, we're just living in it. One of his great contributions to the WPF ecosystem is the WPF Media Kit which adds DVD playback, webcam playback and a number of other capabilities to WPF. One slight deficiency with the webcam control (VideoCaptureElement) is that it doesn't allow simeltaneous recording and display of webcam content....until now!

This code adds simeltaneous video playback and capture to the VideoCaptureElement. VideoCaptureElement gets a "OutputFileName" property which is used to specify where the webcam output will be saved. If this property isn't set then the control functions as before, just showing webcam playback. Most of the changes are in VideoCapturePlayer (VideoCaptureElement is really only a WPF-ized wrapper around VideoCapturePlayer). I've left a copy of the un-modified version of VideoCapturePlayer.cs in the same directory (called VideoCapturePlayer_old.cs) for those who want to look at the differences for themselves, but the main part is where we check to see if the fileName field has been set and if so set up the relevant properties. 

IBaseFilter mux = null;
IFileSinkFilter sink = null;
if (!string.IsNullOrEmpty(this.fileName))
{
    hr = graphBuilder.SetOutputFileName(MediaSubType.Asf, this.fileName, out mux, out sink);
    DsError.ThrowExceptionForHR(hr);

    hr = graphBuilder.RenderStream(PinCategory.Capture, MediaType.Video, m_captureDevice, null, mux);
    DsError.ThrowExceptionForHR(hr);

    // use the first audio device
    var audioDevices = DsDevice.GetDevicesOfCat(FilterCategory.AudioInputDevice);

    if (audioDevices.Length > 0)
    {
        var audioDevice = AddFilterByDevicePath(m_graph,
                                            FilterCategory.AudioInputDevice,
                                            audioDevices[0].DevicePath);

        hr = graphBuilder.RenderStream(PinCategory.Capture, MediaType.Audio, audioDevice, null, mux);
        DsError.ThrowExceptionForHR(hr);
    }
}

hr = graphBuilder.RenderStream(PinCategory.Preview,
                               MediaType.Video,
                               m_captureDevice,
                               null,
                               m_renderer);

The last call to RenderStream() uses a PinCategory of Preview which allows the display of video, the previous calls to RenderStream() were using the Capture pin category, which causes the media to be written to disk. I've updated the sample application that accompanies WPFMediaKit to default to the "webcam sample" screen, and to save the webcam output as a randomly named .wmv file to the "my documents" folder. 

This code is very much proof-of-concept, and I'm concerned about leaks in there, but it does work. One limitation is that the file name can't be set after the graph has been set up, but this seems to be a common limitation with properties on the capture device - to change them you have to re-create the graph.

In any case I hope you find this code useful, and I'll be offering it up to Jeremiah for consideration as a patch to WPFMediaKit.

Free Embeddable Fonts for your WPF Applications

22. November 2009

Using attractive typefaces can add individuality to your application, or reinforce your brand. Although we talked about the means to embed WPF fonts in your application a long time ago, the biggest issue with font embedding is the licensing issues associated with fonts, especially if you’re working on a code sample or free utility. Most fonts, even the multitude that you can download for free online, are not licensed to allow redistribution as part of your application.

Fortunately a small group of fonts has started to be released under a much more permissive license – the SIL Open Font License (OFL) - which specifically allows embedding in applications, both commercial, free and open-source (disclaimer: I am not a lawyer, you should read the license yourself and/or seek legal advice before making any decisions regarding font licensing). This is a very generous move on the part of these type designers who spend considerable time and skill on designing beautiful fonts.

Here is a sample application that uses some of my favourite of OFL-licensed fonts from around the web including Titillium, Goudy Bookletter 1911, and Junction. Great resources for finding new fonts with the OFL license is the Open Font Library and the League of Movable Type.

download source [413 KB] (including fonts!)

From a programming point-of-view it pays to remember this trick from the MSDN for finding the names of embedded fonts. Sometimes the name is not apparent from the file name OR from the info you see in the "Install Font" dialog in windows. Instead you can programatically iterate through the installed fonts using this snippet of code.

// iterates over embedded fonts - assumes you have fonts in a sub-directory called "Fonts" in the project in visual studio
foreach (var fontFamily in Fonts.GetFontFamilies(new Uri("pack://application:,,,/"), "./Fonts/"))
{
    // do stuff with fonts here
}

.NET Framework 4.0 Solves the Single Biggest Problem with WPF Development

20. October 2009

.NET Framework 4.0 solves the single biggest problem with WPF development - The size of the .NET framework redistributable. The full redistributable for the x86 version of the .NET framework weighs in at a svelte 37.71 MB, and the cut-down client profile (that should be suitable for many WPF client applications) is just under 31 MB! For 64-bit platforms (x64 and ia64) the full redistributable are about 55 MB each. They both have the x86 bits included also so x86 .NET applications can run in the WoW. You can get all the details here (including what is in and out of the client profile, how to target etc here). Compared to the 230 MB for the full redistributable for .NET Framework 3.5 sp1 this is a welcome relief. Whatever techniques the .NET framework team have learned putting silverlight on an extreme diet have paid off here too. Lets hope this minification of the framework continues into the RTM version.