Writing a Xaml attached property in C++/CX to resize Images, with a Performance twist

By jay at February 04, 2013 21:41 Tags: , , , , , ,

TL;DR: Writing Xaml/C++ attached properties sometimes gives a 30% improvement over the C# version, which can be caused by the use of events. This article shows code sample for both versions.

 

 

Since it is possible to write a XAML application entirely in C++/CX, I decided to give a try to the performance of some simple code.

There is, after all, some marshaling involved when communicating from C# to native code, particularly with events.

 

The ImageDecodeSizeBehavior

WinRT’s BitmapImage class supports, as does WPF and Silverlight, the DecodePixelWidth and DecodePixelHeight properties.

These are very useful properties that forces the memory surface to store the image to fit a certain size, and avoid the waste of memory induced by large downscaled images. This is a very common performance issue for applications that display variable sized images, where the memory can grow very quickly.

More...

On the Performance of WinRT/Xaml Template Expansion

By jay at February 02, 2013 15:11 Tags: , , , , , ,

TL;DR: Expanding data-bound item templates in Xaml/WinRT in Windows 8 is about a hundred times slower than with Xaml/WPF. This article details how this was measured and a possible explanation.

 

In Windows 8, Microsoft has a introduced a whole new Xaml stack, codenamed Jupiter, completely re-written to be native only.

This allows the creation of Xaml controls using C++ as well as C#.

I will not discuss the philosophical choice of ditching managed WPF in favor of a native rewrite, but make a simple comparison of the performance between the two.

 

Template Expansion Performance

I worked on a project that had performance issues for a UI-Virtualized control, where the initial binding of data as well as the realization of item templates, was having a significant impact on the fluidity of the scrolling of a GridView control.

To isolate this, I created a simple UI: More...

Xaml integration with WinRT and the IXamlMetadataProvider interface

By jay at March 07, 2012 21:04 Tags: , , , , ,

TL;DR: This article talks about the internals of the WinRT/Xaml implementation in Windows 8 and how it deals with databinding, its use of the IXamlMetadataProvider interface, tips & tricks around it, and how to extend the resolver to create dynamic databinding scenarios.

 

Xaml has been around for a while, and it’s been a big part of Silverlight and WPF. Both frameworks are mostly managed, and use a CLR feature known as Reflection, or type introspection.

This is a very handy feature used by Silverlight/WPF to enable late binding to data types, where strings can be used to find their actual classes counter-parts, either for value converters, UserControls, Data-Binding, etc...

 

The burden of .NET reflection

It comes with a cost, though. Reflection is a very expensive process, and up until very recently in Silverlight, there was no way to avoid the use of Reflection. The recent addition of the ICustomTypeProvider interface allows for late binding without the use of reflection, which is a big step what I think is the right direction. Having this kind of interface allows for custom types that define pre-computed lists of fields and properties, without having the runtime to load every metadata available for an object, and perform expensive type safety checks.

This burden of the reflection is particularly visible on Windows Phone, where it is suggested to limit the use of DataBinding, which is performed on the UI thread. The Silverlight runtime needs to walk the types metadata to find observable properties so that it can properly perfrom one or two-way bindings, and this is very expensive.

There are ways to work around this without having ICustomTypeProvider, mainly by generating code that does everything the Xaml parser and DataBinding engines do, but it’s mainly experimental, yet it gives great results.

 

WinRT, native code and the lack of Reflection

In Windows 8, WinRT is pure native code, and now integrates what used to be the WPF/Xaml engine. This new engine can be seen at the cross roads of Silverlight, WPF and Silverlight for Windows Phone. This new iteration takes a bit of every framework, with some tweaks.

These tweaks are mainly related to the fact that WinRT is a native COM based API, that can be used indifferently from C# or C++.

For instance, xml namespaces have changed form and cannot reference assemblies anymore. Declarations that used to look like this :

     xmlns:common="clr-namespace:Application1.Common"

Now look like this :

     xmlns:common="using:Application1.Common"

Where the using only defines the namespace to be used to find the types specified in the inner xaml.

Additionally, WinRT does not know anything about .NET and the CLR, meaning it cannot do reflection. This means that the Xaml implentation in WinRT, to be compatible with the way we all know Xaml, needs to be able to do some kind of reflection.

 

Meet the IXamlMetadataProvider interface

To be able to do some kind reflection, the new Metro Style Applications profile generates code based on the types that are used in the Xaml files of the project. It takes the form of a hidden file, named XamlTypeInfo.g.cs.

That file can be found in the “obj” folder under any Metro Style project that contains a Xaml file. To find it, just click on the “Show all files” button at the top of the Solution Explorer file. You may need to compile the project for it to be generated.

In the entry assembly, the file contains a partial class that extends the App class to make it implement the IXamlMetadataProvider interface. WinRT uses this interface to query for the details of types it found while parsing Xaml files.

This type acts as map for every type used in all Xaml files a project, so that WinRT can get a definition it can understand, in the form of IXamlType and IXamlMember instances. This takes the form of a big switch/case construct, that contains string representation of fully qualified types. See this example :

private IXamlType CreateXamlType(string typeName) 
{ 
  XamlSystemBaseType xamlType = null; 
  XamlUserType userType;

  switch (typeName) 
  { 
    case "Windows.UI.Xaml.Controls.UserControl": 
      xamlType = new XamlSystemBaseType(typeName, typeof(Windows.UI.Xaml.Controls.UserControl)); 
      break;

    case "Application1.Common.RichTextColumns": 
      userType = new XamlUserType(this, typeName, typeof(Application1.Common.RichTextColumns), GetXamlTypeByName("Windows.UI.Xaml.Controls.Panel")); 
      userType.Activator = Activate_3_RichTextColumns; 
      userType.SetContentPropertyName("Application1.Common.RichTextColumns.RichTextContent"); 
      userType.AddMemberName("RichTextContent", "Application1.Common.RichTextColumns.RichTextContent"); 
      userType.AddMemberName("ColumnTemplate", "Application1.Common.RichTextColumns.ColumnTemplate"); 
      xamlType = userType; 
      break; 

  } 
  return xamlType; 
} 

It also creates hardcoded methods that can explicitly get or set the value of every properties a DependencyObject, like this :

case "Application1.Common.RichTextColumns.RichTextContent": 
    userType = (XamlUserType)GetXamlTypeByName("Application1.Common.RichTextColumns"); 
    xamlMember = new XamlMember(this, "RichTextContent", "Windows.UI.Xaml.Controls.RichTextBlock"); 
    xamlMember.SetIsDependencyProperty(); 
    xamlMember.Getter = get_1_RichTextColumns_RichTextContent; 
    xamlMember.Setter = set_1_RichTextColumns_RichTextContent; 
    break;

Note that if you want to step into this code without the debugger ignoring you, you need to disable the “Just my code” feature in the debugger options.

Also, in case you wonder, the Code Generator scans for all referenced assemblies for implementations of the IXamlMetadataProvider interface, and will generate code that will query these providers to find Xaml type definitions.

 

Code Generation is good for you

Now, this code generation approach is very interesting for some reasons.

The first and foremost is performance, because the runtime does not need to use reflection to determine what can be computed at runtime. This is a enormous performance gain, and this will be beneficial for the perceived performance as the runtime will not waste precious CPU cycles to compute data that can be determined at compile time.

More generally, in my projects, I've been using this approach of generating as much code as possible, to avoid using reflection and waste time and battery on something that can be only done once and for all.

The second reason is extensibility, as this IXamlMetadataProvider can be extended to add user-provided types that are not based on DependencyObject. This is an other good impact on performance.

 

Adding custom IXamlMetadataProvider

It is possible to extend the lookup behavior for standard types that are not dependency objects. This opens the same range of scenarios that ICustomTypeProvider provides.

All that is needed is to implement the IXamlMetadataProvider interface somewhere in an assembly, and the code generator used for XamlTypeInfo.g.cs will pick those up and add them in the Xaml type resolution chain. Note that for some unknown reason, it does not work in the main assembly but only for referenced assemblies.

Every time the databinding engine will need to get the value behind a databinding expression, it will call the IXamlMetadataProvider.GetXamlType method to get the definition of that type, then get the databound property value.

A very good feature, if you ask me.

 

The case of hidden DependencyObject

By hidden dependency properties, I’m talking about DependencyObject types that are not directly referenced in Xaml files. This can be pretty useful for complex controls that generate convention based databinding, such as the SemanticZoom control, that provides a implicit “Key” property to perform the Zoomed out view.

Since this XamlTypeInfo.g.cs code is generated from all known Xaml files, this means that these hidden DependencyObject types that do not have code generated for them. This forces the CLR to intercept these failed requests and fallback on actual .NET reflection based property searching for databinding, which is not good for performance.

This fallback behavior was not implemented in the Developer Preview, and the binding would just fail with a NullReferenceException without any specific reason given to the developer.

 

The case of Xaml files located in another assembly

If your architecting a bit your solution, you’re probably using MVVM or a similar pattern, and you’re probably putting your views in another assembly.

If you do that, this means that there will not be any xaml file in your main assembly (aside from the App.xaml file), leading to an empty XamlTypeInfo.g.cs file. This will make any type resolution requested by WinRT fail, and your application will mostly likely not run.

In this case, all you need to do is create a dummy Xaml file that will force the generation of the XamlTypeInfo.g.cs, and basically make your layer separation work.

 

Until next time, happy WinRT'ing !

[Rx] Using the ObserveOn and SubscribeOn operators

By jay at July 24, 2011 20:04 Tags: , , , , ,

TLDR: This post talks about how the Reactive Extensions ObserveOn operator changes the execution context (the thread) of the IObservable OnNext/OnComplete/OnError methods, whereas the SubscribeOn operator changes the execution context of the implementation of the Subscribe method in the chain of observers. Both methods can be useful to improve the performance of an application's UI by putting work on background threads.

 

When developing asynchronous code, or consuming asynchronous APIs, you find yourself forced to use specific methods on a specific thread.

The most prominent examples being WPF/Silverlight and Winforms, where you cannot use UI bound types outside of the UI Thread. In the context of WPF, you'll find yourself forced to use the Dispatcher.Invoke method to manipulate the UI in the proper context.

However, you don't want to execute everything on the UI Thread, because the UI performance relies on it. Doing too much on the UI thread can lead to a very bad percieved performance, and angry users...

 

Rx framework's ObserveOn operator

I've discussed a few times the use of ObserveOn in the context of WP7, where it is critical to leave the UI thread alone and avoid choppy animations, for instance.

The ObserveOn operator changes the context of execution (scheduler) of a chain of operators until an other operator changes it.

To be able to demonstrate this, let's write our own scheduler :

public class MyScheduler : IScheduler
{
    // Warning: ThreadStatic is not supported on Windows Phone 7.0 and 7.1
    // This code will not work properly on this platform.
    [ThreadStatic]
    public static int? SchedulerId;

    private int _schedulerId;
    private IScheduler _source;
        
    public MyScheduler(IScheduler source, int schedulerId)
    {
        _source = source;
        _schedulerId = schedulerId;
    }

    public DateTimeOffset Now { get { return _source.Now; } }

    public IDisposable Schedule<TState>(
              TState state, 
              Func<IScheduler, TState, IDisposable> action
           )
    {
        return _source.Schedule(state, WrapAction(action));
    }

    private Func<IScheduler, TState, IDisposable> WrapAction<TState>(
              Func<IScheduler, TState, IDisposable> action)
    {
        return (scheduler, state) => {

            // Set the TLS with the proper ID
            SchedulerId = _schedulerId;

            return action(_source, state);
        };
    }
}

This scheduler's purpose is to intercept calls to the ISchedule methods (You'll fill the missing Schedule methods by yourself) and flag them with a custom thread ID. That way, we'll know which scheduler is executing our code.

Note that this code will not work properly on Windows Phone 7, since ThreadStaticAttribute is not supported. And it's still not supported on 7.1... Seems like not enough people are using ThreadStatic to make its way to the WP7 CLR...

Anyway, now if we write the following Rx expression :

Observable.Timer(TimeSpan.FromSeconds(1), new MyScheduler(Scheduler.ThreadPool, 42))
          .Do(_ => Console.WriteLine(MyScheduler.SchedulerId))
          .First();

We force the timer to raise OnNext on the ThreadPool through our scheduler, and we'll get the following :

42

Which means that the lambda passed as a parameter to the Do operator got executed in the context of the Scheduler used when declaring the Timer operator.

If we go a bit farther :

Observable.Timer(TimeSpan.FromSeconds(1), new MyScheduler(Scheduler.ThreadPool, 42))
          .Do(_ => Console.WriteLine("Do(1): " + MyScheduler.SchedulerId))
          .ObserveOn(new MyScheduler(Scheduler.ThreadPool, 43))
          .Do(_ => Console.WriteLine("Do(2): " + MyScheduler.SchedulerId))
          .ObserveOn(new MyScheduler(Scheduler.ThreadPool, 44))
          .Do(_ => Console.WriteLine("Do(3): " + MyScheduler.SchedulerId))
          .Do(_ => Console.WriteLine("Do(4): " + MyScheduler.SchedulerId))
          .First();

We'll get the following :

Do(1): 42
Do(2): 43
Do(3): 44
Do(4): 44

Each time a scheduler was specified, the following operators OnNext delegates were executed on that scheduler.

In this case, we're using the Do operator which does not take a scheduler as a parameter. There some operators though, like Delay, that implicitly use a scheduler that changes the context.

Using this operator is particularly useful when the OnNext delegate is performing a context sensitive operation, like manipulating the UI, or when the source scheduler is the UI and the OnNext delegate is not related to the UI and can be executed on an other thread.

You'll find that operator handy with the WebClient or GeoCoordinateWatcher classes, which both execute their handlers on the UI thread. Watchout for Windows Phone 7.1 (mango) though, this may have changed a bit.

 

An Rx Expression's life cycle

Using an Rx expression is performed in a least 5 stages :

  • The construction of the expression,
  • The subscription to the expression,
  • The optional execution of the OnNext delegates passed as parameters (whether it be observers or explicit OnNext delegates),
  • The observer chain gets disposed either explicitly or implicitly,
  • The observers can optionally get collected by the GC.

The third part's execution context is covered by ObserveOn. But for the first two, this is different.

The expression is constructed like this : 

var o = Observable.Timer(TimeSpan.FromSeconds(1));

Almost nothing's been executed here, just the creation of the observers for the entire expression, in a similar way IEnumerable expressions work. Until you call the IEnumerator.MoveNext, nothing is performed. In Rx expressions, until the Subscribe method is called, nothing is happening.

Then you can subscribe to the expression :

var d = o.Subscribe(_ => Console.WriteLine(_));

At this point, the whole chain of operators get their Subscribe method called, meaning they can start sending OnNext/OnError/OnComplete messages.

 

The case of Observable.Return and SubscribeOn

Then you meet that kind of expressions :

Observable
   .Return(42L)
   // Merge both enumerables into one, whichever the order of appearance
   .Merge(
      Observable.Timer(
         TimeSpan.FromSeconds(1), 
         new MyScheduler(Scheduler.ThreadPool, 42)
      )
   )
   .Subscribe(_ => Console.WriteLine("Do(1): " + MyScheduler.SchedulerId));

Console.WriteLine("Subscribed !");

This expression will merge the two observables into one that will provide two values, one from Return and one from the timer.

And this is the output :

Do(1):
Subscribed !
Do(1): 42

The Observable.Return OnNext was executed during the call to Subscribe, and has that thread has no SchedulerId, meaning that a whole lot of code has been executed in the context of the caller of Subscribe. You can imagine that if that expression is complex, and that the caller is the UI Thread, that can become a performance issue.

This is where the SubscribeOn operator becomes handy :

Observable
   .Return(42L)
   // Merge both enumerables into one, whichever the order of appearance
   .Merge(
      Observable.Timer(
         TimeSpan.FromSeconds(1), 
         new MyScheduler(Scheduler.ThreadPool, 42)
      )
   )
   .SubscribeOn(new MyScheduler(Scheduler.ThreadPool, 43))
   .Subscribe(_ => Console.WriteLine("Do(1): " + MyScheduler.SchedulerId));

Console.WriteLine("Subscribed !");

You then get this :

Subscribed !
Do(1): 43
Do(1): 42

The first OnNext is now executed under of a different scheduler, making subscribe a whole lot faster from the caller's point of view.

 

Why not always Subscribe on an other thread ?

That might come in handy, but you may not want that as an opt-out because of this scenario :

Observable.FromEventPattern(textBox, "TextChanged")
          .SubscribeOn(new MyScheduler(Scheduler.ThreadPool, 43))
          .Subscribe(_ => { });

Console.WriteLine("Subscribed !");

You'd get an "Invalid cross-thread access." System.UnauthorizedAccessException, because yo would try to add an event handler to a UI element from a different thread. 

Interestingly though, this code does not work on WP7 but does on WPF 4.

An other scenario may be one where delaying the subscription may loose messages, so you need to make sure you're completely subscribed before raising events.

 

So there you have it :) I hope this helps you understand a bit better those two operators.

Binding a C# property to a WPF validated Control

By Jerome at August 29, 2007 05:48 Tags: , ,

The DataBinding in WPF allows the binding of control properties to many things, like other control properties, arrays, data providers, ... But it can also bind a control property to a property defined by code on the C# side.

It is interesting to bind to C# property to be able to have the integrated WPF validation and still use a simple property from the code. In that case, I wanted to have the validation of a TextBox displaying a DateTime object.

Here's how to do this.

On the C# side :


public partial class Window1 : Window

  public Window1() 
  {   
    MyDate = DateTime.Now;
    InitializeComponent();
  }
  public DateTime MyDate { get; set; }
}
 

Note that I'm using the latest C# 3.0 syntax to declare variable-less properties. This is compiler trick, the variable is still declared at compile time, but since I don't need to have a specific code in the get or set accessor, it can stay in this short form.

Now on the XAML side :


<Window ... >

  <TextBox Width="100" Height="20">

    <Binding Path="MyDate" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}" UpdateSourceTrigger="PropertyChanged">

      <Binding.ValidationRules>

        <ExceptionValidationRule />

      </Binding.ValidationRules>

    </Binding>

  </TextBox>

</Window>

The interesting part here is the use of RelativeSource and the FindAncestor mode. Here, we're looking for the property MyDate from the nearest ancestor instance of the Window type, from the current instance.

This way, you'll have a validated date time in your property value. Just make sure you're checking that the value is really valid using the System.Windows.Controls.Validation class.

WPF DataBinding and Application Settings

By Jerome at February 15, 2007 21:47 Tags: ,

Well, yet an other post on WPF and some DataBinding. But this time, this is about DataBinding to application settings that are automatically generated by visual studio. These settings come in handy when you want to save your application settings per user, or have some application wide settings. In my case, I wanted to have my application to remember its size and position, as well as the window state.

WinForms were providing an UI to do this, and I wanted to have all that functionality back. It is not all that "visual" as WinForms can do it, but it works rather well. I guess that Orcas will provide a way to do this visually.

All I had to do to use these settings from XAML was to create a resource to be usable for DataBinding, from a separate file :


File: SettingsRes.xaml



<ResourceDictionary xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation

                    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml 

                    xmlns:settings = "clr-namespace:WindowsApplication2.Properties">

  <ResourceDictionary.MergedDictionaries>

    <ResourceDictionary>

      <settings:Settings x:Key="settings" />

    </ResourceDictionary>

  </ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

WindowsApplication2 is the default namespace for the application, and since the Settings class is automatically generated, the default namespace is used. This resource will be used application wide and is referenced like this :


<Application.Resources>

  <ResourceDictionary>

    <ResourceDictionary.MergedDictionaries>

      <ResourceDictionary Source = "SettingsRes.xaml"/>

    </ResourceDictionary.MergedDictionaries>

  </ResourceDictionary>

</Application.Resources>

This is handy because resources are separated in multiple files. I also add here references to value converters, when I have to use them everywhere in the application. Value converters, yet an other interesting subject. Maybe in an other post :)

Now, about binding the data. We want to bind the Width, Height and WindowState of the default Window to some settings in the ApplicationSettings.

Here's what to do :


<Window x:Class="WindowsApplication2.Window1"

        xmlns = http://schemas.microsoft.com/winfx/2006/xaml/presentation

        xmlns:x = http://schemas.microsoft.com/winfx/2006/xaml

        Height = "{Binding Source={StaticResource settings}, Path=Default.MainWidth, Mode=TwoWay}"

        Width = "{Binding Source={StaticResource settings}, Path=Default.MainHeight, Mode=TwoWay}"

        WindowState = "{Binding Source={StaticResource settings}, Path=Default.MainState, Mode=TwoWay}">

We create three bindings, each for an attribute, and set the source to the "settings" resource. The interesting part here is that the even thought the property we use is static, Settings.Default here, the Binding engine does seem to support it.

Setting the binding path to Default.MainWidth binds to the appropriate property. The last parameter instructs the binding to set the value of the property when the binding destination value changes, which can be the actual window height, for instance. The type of the property does not need to match the destination exact type, and since the type of the WindowState property is not known by VS2005 settings designer by default, setting the type to string seems to be enough.

Simple and easy. Now my application remembers where it was !

The sample here is a bit more complex, since it includes code to actually save the settings. But this is nothing really complex.

Man ! I like WPF... !

WPF DataContext and CurrentItem

By Jerome at February 13, 2007 15:23 Tags: , ,

DataBinding is one of the technologies I like the most. 

Winforms did a fine job introducing the concept, but it was pretty easy to be stuck when trying to perform complex databinding. .NET 2.0 brought the concept of BindingSource, which eased the management of multiple "Current items" on a single form. You might have encountered this when creating multiple master/detail views on the same form. That was the case when you wanted to walk through a set of tables through their relations, say down to three levels.

WPF has a far more advanced DataBinding engine and introduces the concept of DataContext. There's the notion of a hierarchy of DataContexts and a databound control uses the nearest DataContext available.

An example is better than a thousand words. Here's a data source :


<xmldataprovider x:key="ops" xpath="/data/level1">

  <x:XData>

    <data xmlns="">

      <level1 name="1">

        <level2 name="1-1">

          <level3 name="test">Some Value</level3>

          <level3>Yet an other value from level 3</level3>

        </level2>

        <level2 name="1-2">

          <level3>Some other Value</level3>

          <level3>Yet an other Value</level3>

        </level2>

      </level1>

      <level1 name="2">

        <level2 name="2-1">

          <level3>Some Value</level3>

          <level3>Yet an other value from level 3</level3>

        </level2>

        <level2 name="2-2">

          <level3>Some other Value</level3>

          <level3>Yet an other Value</level3>

        </level2>

      </level1>

    </data>

  </x:XData>

</xmldataprovider>


It's a three level hierarchy, and I want to display this data, by recursively selecting each level in a ListBox to see its content.

Now, let's bind this data to a list box, contained in a GroupBox to be a bit more readable :


<GroupBox Header="Level 1" DataContext="{Binding Source={StaticResource ops}}">

  <ListBox ItemsSource="{Binding}"

           DisplayMemberPath="@name"

           IsSynchronizedWithCurrentItem="True" />

</GroupBox>

This performs a binding to the attribute "name" of the level1 node list. The IsSynchronizedWithCurrentItem tells the listbox to set the CurrentItem of the current DataContext, which can be used to fill the next ListBox for the level.

Now, to add a new DataContext level, let's add a new GroupBox, and a stack panel to have a nice layout :


<GroupBox Header="Level 1"

          DataContext="{Binding Source={StaticResource ops}}">

  <StackPanel Orientation="Horizontal">

    <ListBox ItemsSource="{Binding}"

             DisplayMemberPath="@name"

             IsSynchronizedWithCurrentItem="True" />

    <GroupBox Header="Level2"

              DataContext="{Binding Path=CurrentItem}">

      <ListBox ItemsSource="{Binding}"

               DisplayMemberPath="@name"

               IsSynchronizedWithCurrentItem="True" />

    </GroupBox>

  </StackPanel>

</GroupBox>

Now, there is a new DataContext for any children of the second group box, and is having the CurrentItem of the upper DataContext as a root. This is fairly easy to do, so let's do this for the final level.


<GroupBox Header="Level 1"

          DataContext="{Binding Source={StaticResource ops}}">

  <StackPanel Orientation="Horizontal">

    <ListBox ItemsSource="{Binding}"

             DisplayMemberPath="@name"

             IsSynchronizedWithCurrentItem="True" />

    <GroupBox Header="Level2"

              DataContext="{Binding Path=CurrentItem}">

      <StackPanel Orientation="Horizontal">

        <ListBox ItemsSource="{Binding}"

                 DisplayMemberPath="@name"

                 IsSynchronizedWithCurrentItem="True" />

        <GroupBox Header="Level3"

                  DataContext="{Binding Path=CurrentItem}">

          <StackPanel Orientation="Horizontal">

            <ListBox ItemsSource="{Binding}"

                     IsSynchronizedWithCurrentItem="True" />

            <Label Content="{Binding Path=CurrentItem}" />

          </StackPanel>

        </GroupBox>

      </StackPanel>

    </GroupBox>

  </StackPanel>

</GroupBox>

Each time a new DataContext is set, a new CurrentItem is created. That kind of behavior was hard to reproduce using DataBinding with WinForms; WPF allows it only by using a simple declarative syntax. Easy and powerful.

Also there is a fine feature that came up when using this DataContext and CurrentItem : The CurrentItem "chain" for a specific path is -- when the data source does not change -- kept if you change the selection, and come back to that particular path. Pretty interesting.

Here is a working xaml sample of this post.

Did I say that a really like WPF already ? :)

WPF, Xml namespace and XmlDataProvider

By Jerome at January 30, 2007 16:15 Tags: ,

I was playing with the XmlDataProvider in WPF and I wanted to bind the content of inline XML from that provider to a ComboBox.

So, with I wrote this little piece of code :

<XmlDataProvider x:Key="ops" XPath="/operations/op">  <x:XData>    <operations>      <op>A</op>      <op>B</op>      <op>C</op>    </operations>  </x:XData></XmlDataProvider>[...]<ComboBox   ItemsSource="{Binding Source={StaticResource ops}}" />

Turns out that the combobox does not display anything, even though the XPath for the XmlDataProvider is correct and the ItemSource binding as well.

In reality, the problem is not in the binding but rather in the XPath, where the XML "operations" node in the inline xml inherits from the System.Windows XML namespace, which renders the XPath "/operations/op" ineffective. In that case, the XPath expression selects nodes from the "" (empty) namespace.

I just needed to write this instead :

<XmlDataProvider x:Key="ops" XPath="/operations/op">  <x:XData>    <operations xmlns="">

to reset the namespace used for that node, and my ComboBox was filled ! 

As a side note on WPF, I am just wondering on how this technology will be adopted. Many concepts are fairly innovative and differ from the usual concepts found in Winforms or even MFC.

I'm convinced that it is definitely going in the right direction with the data and design separation, but I'm not sure on how beginners are going to apprehend all this. Maybe a new release of Cider is going to ease development with this technology...Wait and see. 

Meanwhile, I'm continuing to enjoy the fact that I can databind a TreeView very easily :)

About me

My name is Jerome Laban, I am a Software Architect, C# MVP and .NET enthustiast from Montréal, QC. You will find my blog on this site, where I'm adding my thoughts on current events, or the things I'm working on, such as the Remote Control for Windows Phone.