I’m getting errors in the Visual Studio Designer using a custom Attached Property, help!

13. January 2008

If you’ve written your own custom attached property in WPF you may come across the following error when you try to look at a Window, Page or UserControl that attempts to use the attached property in the WPF designer in Visual Studio 2008:

The Property '[your custom attached property name]' is read-only and cannot be changed

The puzzling thing is that you can get this error message even if your attached property is not defined as read-only, and has a setter and isn’t registered as read-only in the Property Meta-data. Even more confusingly the property can seem fine and working correctly at run-time.

So what’s going on? Although the error message is a little cryptic the error is caused by a type mismatch between the property type of the dependency property (when it is registered) and the second parameter accepted by the “Set[YourPropertyName]” method that is defined when creating an attached property. For example if you’ve registered an attached property like this: 

public static readonly DependencyProperty MyCustomProperty =
   DependencyProperty.RegisterAttached("MyCustom", typeof(MyOtherType), typeof(MyType));

The property meta-data system expects that when you set this attached property the value will be of MyOtherType (the second type parameter is the type that "owns" the dependency property, usually the type you declare the DP in). Type WPF designer is aware of this, for example if you attempt to assign this property in XAML from a string and no appropriate converter from string to MyOtherType is present it shows an error.

However as part of your attached property declaration you are also obliged to create "Get[PropertyName]" and "Set[PropertyName]" wrapper methods for getting and setting the attached properties.

public static void SetMyCustom(DependencyObject depObj, TheWrongType value)
{
   depObj.SetValue(MyCustomProperty, value);
}

If we include the wrong type as the second parameter in one of these declarations – in this case a type that is not assignable from MyOtherType - this isn’t a compile time error (because these methods aren’t part of any interface we’re implementing or generic type) and may work fine at run-time if that code path isn’t called (I believe that XAML bypasses the property wrappers). The designer does pick up on the discrepancy, and considers that type dependency property is read-only because it couldn’t find an appropriately typed "Set[YourPropertyName]” method. Of course this error is easy to resolve once you know the cause, by changing the type of the second parameter to be the same as, or assignable from the type that was used when you declared the dependency property.

What is the equivalent of the ASP.NET Repeater in WPF?

16. December 2007

The ASP.NET repeater is a great control for creating an arbitrary templated look for lists of data in ASP.NET web applications. WPF's databinding bears a great deal of similarity to the templating support found in the repeater, taking the power of templating even further by allowing templates to be defined as resources and re-used in multiple contexts, and in lots of different types of controls. However in spite of this there is no Repeater control in WPF.

Sample Repeater (from MSDN)
<asp:Repeater id="Repeater1" runat="server">
  <HeaderTemplate>
    <table border="1">
       <tr>
          <td><b>Company</b></td>
          <td><b>Symbol</b></td>
       </tr>
   </HeaderTemplate>
   <ItemTemplate>
     <tr>
       <td> <%# DataBinder.Eval(Container.DataItem, "Name") %> </td>
       <td> <%# DataBinder.Eval(Container.DataItem, "Ticker") %> </td>
     </tr>
   </ItemTemplate>
   <FooterTemplate>
     </table>
   </FooterTemplate>
</asp:Repeater>

How can you replicate the functionality  of the repeater in WPF? It turns out this is quite easy using an ItemsControl. ItemsControl is the base type that lots of list-like controls in WPF like ListBox, ComboBox and Menu which inherit from it either directly or indirectly. ItemsControl is also the parent to some list-like controls you might not expect such as the toolbar (which is really just a list of buttons and other controls, usually laid out horizontally) and StatusBar (once again, usually just a kind of horizontal list of controls). In spite of its fairly fundamental nature to lots of the usual suspects in the WPF controls namespace it isn't an abstract type and can be created in markup and bound like this:

ItemsControl Xaml Code
<ItemsControl ItemsSource="{Binding}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <!-- apply additional customizations for
      the items here in the template -->

      <TextBlock Text="{Binding}" />
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

The <DataTemplate> element allows us to specify how we want each item the ItemsControl is bound to, and the ItemsSource property on the ItemsControl populates the bound items from the data context (I'm assuming for the purposes of this demo that the stuff you want to bind to is in there). Another thing you may wish to do with the ItemsControl is to place it inside of a ScrollViewer control. The ASP.NET repeater generates HTML which is hosted in the browser, which handles showing a scroll-bar if the document is longer than can be displayed on a single screen. WPF Windows and Pages don't default to this way of operating, and thus you probably want to add the scroll viewer if more items are added to the ItemsControl than can be displayed inside the Window or Page.

Here is a complete page showing the list of binding modes available in WPF displayed in an ItemsControl. The ItemsControl has an ItemsPanel property that the bound items are layed out in. The default is a StackPanel, which is they type of panel you would want to reproduce the functionality of the ASP.NET Repeater. In this example below we've used the UniformGrid instead to control the layout of the items being bound. You can click here to run this page in your browser.

<Page
  xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation "
  xmlns:x="
http://schemas.microsoft.com/winfx/2006/xaml "
  xmlns:d="clr-namespace:System.Windows.Data;assembly=PresentationFramework"
  xmlns:sys="clr-namespace:System;assembly=mscorlib"
  >
    <Page.Resources>
        <ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="bindingNames">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="d:BindingMode"/>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Page.Resources>
    <ItemsControl ItemsSource="{Binding}" DataContext="{StaticResource bindingNames}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <!-- apply additional customizations for the items here in the template -->
                <TextBlock Text="{Binding}" FontSize="22"
                           Margin="5" Foreground="#feca00" />
        </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Page>

How can I provide my own Main() method in my WPF application?

13. December 2007

When you create a WPF application in Visual Studio the 'entry point' for the process, where the application is created and the first form displayed, is not directly apparent. Instead the start-up behaviour is controlled by setting attributes on the App.xaml, such as which form to start. At compile-time WPF generates the real entry point method using the classic static void Main() method signature in C#, or Public Shared Sub Main() in VB.NET. Inside the Main() method WPF creates an instance of one of your classes which derive from System.Windows.Application, and calls the blocking Run() method on this Application-derived class which keeps the process "alive". Generally this is a useful abstraction, hiding away some of the lower-level details of how the WPF application starts up, however sometimes you want to provide your own version of the Main() method. So how do you tell WPF to use your main method and not its own?

The way WPF knows to create the Main() method for a particular xaml file is through the build action property set for App.xaml - it has a build action of ApplicationDefinition. By changing this to Page WPF won't create the Main method and you can provide your own in a regular class file you add to the project.

Changing the Build Action for App.xaml

It is important to note that when you provide your own Main() method that the method should be adorned with the STAThread attribute, which sets the threading model for the process. You can either look at the current generated Main() method for your project as a starting point (it should be in the obj folder) or use the following code:

[System.STAThreadAttribute()]
static void Main()
{
    YourApplicationName app = new YourApplicationName();
    app.InitializeComponent();
    app.Run();
}

WPF-specific Snippets in Visual Studio 2008

29. November 2007

Visual Studio 2008 comes with some useful snippets for WPF development out of the box. In C# type propa followed by two TAB keystrokes inserts the a snippet for an attached dependency property, including a getter, setter and the registration code.

Similarly propdp followed by two TAB keystrokes inserts a snippet for a dependency property. As you would expect the snippet for this is very similar to the attached dependency property, except in this case it calls DependencyProperty.Register() instead of DependencyProperty.RegisterAttached().

The C# snippet in action

Visual Basic in Visual Studio 2008 has even more snippets defined including RoutedCommand and RoutedEvent registration snippets, and a RoutedCommand handler snippet. I'm primarily a C# kind of guy, so I never realized that VB.NET had the two snippets I mentioned above for C# in VS2005 (with the VS Extensions for .NET 3.0 installed). It seems in this case C# is playing catch-up to VB.NET.

You can look at all the snippets (not just the WPF-specific ones) by selecting "Tools->Code Snippet Manager" from the VS menu. You can of course define your own snippets, but it is nice to see these ones built in to VS2008.

How Big is WPF?

27. November 2007

One thing people often ask me about WPF is the learning curve - how long will it take for me to be productive, and how long before I know the "whole api". The sad fact is that knowing the "whole" of WPF is a difficult proposition, due to its size. A lot has been written about the learning curve associated with the XAML programming model and the vector-based retained rendering system, but regardless of these factors WPF is going to have a learning curve due just to its size. WPF is big by any standard - with almost 1600 public types in v3.0 and almost 3600 classes it is approximately the same size as Windows Forms and ASP.NET combined. It spans 3 main assemblies PresentationCore.dll, PresentationFramework.dll and WindowsBase.dll (I'm excluding the Aero, Classic, Luna and Royale "theme" assemblies, and the UI automation and ReachFramework in my calculation of the size since they are not WPF specific). The good news is that you don't need to know the "whole api" in order to be productive and start using WPF. Here's a helpful infographic to convey the message:

ASP.NET 2.0 WinForms 2.0 WPF
1098 public types
1551 classes
777 public types
1500 classes
1577 public types
3592 classes

Visual Studio 2008 and .NET Framework 3.5 Released

24. November 2007

Visual Studio 2008 and .NET Framework 3.5 were released earlier this week. Visual Studio 2008 is the first version of Visual Studio released since WPF and the rest of .NET Framework 3.0 were released a year ago. VS2008 includes a WPF designer and XAML editor, and allows targeting of .NET 3.0 or .NET 3.5 when developing and compiling solutions.

.NET Framework 3.5 includes a host of new language features for C# 3.0 and VB9. Most of these language features exist primarily to support LINQ, however .NET 3.5 also includes some enhancements to WPF. An overview of the changes in 3.5 can be found here on MSDN. Kevin Moore also recorded an interview for Channel9 before he left Microsoft discussing some of the changes that were coming in 3.5. Dr Tim Sneath also listed off 15 of his favourite enhancements to WPF here.

Some of my favourite enhancements for WPF in .NET 3.5 are supporting XBAP applications in FireFox (on versions of Windows) and the data binding and IErrorProvider enhancements (thanks in part to Paul Stovell). 

How can I Change the Size and Color of the Stylus Input in the InkCanvas?

22. October 2007

WPF’s InkCanvas control provides a quick and easy way to add ink input to your application. By default the strokes in the InkCanvas are thin black lines, which may be too thin or difficult to see in some instances. Fortunately the appearance of the strokes can easily be changed by modifying the DefaultDrawingAttributes property of the InkCanvas which is of type DrawingAttributes.

<InkCanvas>
  <InkCanvas.DefaultDrawingAttributes>
    <DrawingAttributes Color="Red" Width="5" />
  </InkCanvas.DefaultDrawingAttributes>
</InkCanvas>

red inkcanvas strokes in a smiley face

The DrawingAttributes has a number of other interesting properties, such as the FitToCurve property which makes lines drawn in the canvas smoother. It is set to false by default. This property seems to have less of an effect when using a tablet input device. When “drawing” with the mouse you can notice the difference more easily.
InkCanvas elements with different fittocurve settings


Setting the IsHighlighter property to true causes the strokes to be drawn semi-transparently to allow content behind them to show through.


The IgnorePressure property defaults to false and uses pressure information from devices capable of sending it (like input tablets) to alter the thickness of the line.


You can also set the shape of the stylus tip to rectangular or elliptical by setting the StylusTip property.

How can I have my WPF application start in “kiosk” mode?

24. September 2007

For some kinds of applications displaying as “maximised” is not enough, either because they want to make use of every single pixel of screen-space possible, or because displaying the task bar and associated window trimmings would be distracting or confusing for users of the application. The PowerPoint slide viewer is a good example of this, starting in “kiosk” mode to create a more immersive presentation and preventing audience members becoming distracted by the task bar and things in the notification area. Fortunately doing this for your own WPF application can be achieved quite easily by setting the WindowStyle and WindowState properties on the Window as shown below.

Xaml Code
<Window x:Class="LearnWPF.KioskMode.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="LearnWPF.KioskMode"
    WindowStyle="None"
    WindowState="Maximized">

WindowStyle should be set to None (this draws the window without any border, and is the same state you can use to create a WPF splash screen) and the WindowState set to Maximized. These properties can also be set from code. One small issue we have observed is if you try to change the WindowStyle in code after the WindowState has changed to Maximized the resulting window will be drawn without a border, but won’t display over the top of the status bar.

Free Vector Images for your WPF Projects

11. September 2007

If you're from further down the developer end of the designer-developer spectrum chances are you've been avoiding creating your own images, and on the look-out for some good XAML icons and vector images to include in your application, since bitmap images often look blurry. While we included some XAML image resources in the past there are plenty of other good resources out on the web if you know what to look for. Although no graphic designers are sitting at home churning out XAML code per-se, there are plenty of ways to convert the vector content they produce (like SVG files or Adobe Illustrator .ai files) to XAML.  Here we've included two sites to get you started, and approaches for converting other vector formats into XAML.

OpenClipArt.org is a repository of "open source" vector art stored in SVG format. SVG is an XML-based vector format (and thus you could transform it yourself to XAML if you wished), however there is already an excellent tool from Andrej Benedik from WPF-graphics.com for doing this. You can also use the free and open-source InkScape editor to edit SVG files. Many of the images are licensed in the public domain, meaning you can use them for pretty much any purpose. Shown below is a mac-like SVG image of a new computer by "big red smile" (possibly not their real name)  beside the converted XAML version displayed in Kaxaml.

vecteezy.com is a "free vector art of the day" type site, with nice vector backgrounds and images released under a variety of terms (so make sure you check the license on the image). Most of the files here are Adobe Illustrator .ai files. If you have Illustrator installed you can use Mike Swanson's exporter, however if you're a developer that is less likely. Expression Design (now included in MSDN universal) can import Illustrator .ai files. For some reason it can't open them directly (if you select File->Open and then try to browse for a .ai file it won't let you) so you need to create a new blank file, and then select File->Import and browse for the .au file. Once in Expression Design you select File->Export and select Xaml as the type from the dropdown list. You can then choose how the xaml is formed when you export it.

Real-World WPF Start Time Perf Tip - Delay Setting the DataContext

3. September 2007

.NET applications traditionally suffer from slower startup time than native applications, caused by the time to load the .NET framework DLLs, JIT time etc. WPF applications have further things that can slow down cold start-time, the extra PresentationCore, PresentationFramework and WindowBase assemblies that need to be loaded and the start-up of the PresentationFontCache service. Any tips to help improve start time is therefore most welcome.

Doug Stockwell recently released an updated version (v1.6 build 2802) of his free RikReader WPF-based RSS Reader, with considerably-improved start time. I've been using RikReader as my primary RSS reader since it was first released, and in previous versions the start time stood out as a blemish on an otherwise excellent app. The performance characteristics of older versions of RikReader were a little different to usual applications, in that the hot start-times were still quite bad (>10 seconds for my list of a couple of hundred feeds), whereas the new version hot-starts in about 4 seconds (roughly equivalent to Expression Blend, Thoughtex and most other WPF applications I use). Cold start-times for RikReader had also improved noticeably.

I contacted Doug to find out what he'd done to achieve this great improvement, and was pleased to hear of the simple change he had made. Instead of using XAML to declaratively set the DataContext for his main window, which contained all the RSS feed data, he switched to setting it programmatically in the Application.OnActivated. This sounds like a tip that would improve the perceived performance of the app (making the main window display more quickly) without improving the actual performance, however it seems to have also improved the actual start time considerably. As with all things performance-related your mileage may vary, and it pays to measure yourself. Fortunately the simplicity of this change means it will be easy to swap between the two methods of setting the DataContext.