Yesterday I played around with WPF resources and stumbled on a very strange behavior, Check out this code

   1: <Window.Resources>
   2: 
   3:         <Style TargetType="ListBox">
   4:             <Setter 
                   Property="HorizontalAlignment"
                   Value="Center" />
   5:         </Style>
   6: 
   7:         <x:Array x:Key="List" 
                      Type="{x:Type sys:String}">
   8:             <sys:String>A</sys:String>
   9:             <sys:String>B</sys:String>
  10:             <sys:String>C</sys:String>
  11:             <sys:String>D</sys:String>
  12:             <sys:String>E</sys:String>
  13:         </x:Array>
  14: 
  15:     </Window.Resources>
  16: 
  17:     <StackPanel>
  18:         <ListBox x:Name="LstBox"
  19:                  ItemsSource="{Binding Source={StaticResource List}}">
  20:         </ListBox>
  21:     </StackPanel>

Nothing our of the ordinary, an array, a Listbox binded to that array and  and a style for the Listbox. Now starts the fun, if you compile and run this code you get nothing, the ListBox is empty!

ListBox Style

The little thing in the red circle is the ListBox :). I kept on playing with it to check what is the problem and finally I got the following code which solved the problem:

   1: <Window.Resources>
   2: 
   3:         <x:Array x:Key="List" Type="{x:Type sys:String}">
   4:             <sys:String>A</sys:String>
   5:             <sys:String>B</sys:String>
   6:             <sys:String>C</sys:String>
   7:             <sys:String>D</sys:String>
   8:             <sys:String>E</sys:String>
   9:         </x:Array>
  10: 
  11:         <Style TargetType="ListBox">
  12:             <Setter Property="HorizontalAlignment" Value="Center" />
  13:         </Style>
  14:
  15:     </Window.Resources>
  16: 
  17:     <StackPanel>
  18:         <ListBox x:Name="LstBox"
  19:                  ItemsSource="{Binding Source={StaticResource List}}">
  20:         </ListBox>
  21:     </StackPanel>

Can you see the difference? It’s subtle…

I just changed the position of the Style and the Array and magically it worked! How about that? now the window looks like this:

Array Binding 

Things just got personal! I have decided to play around a bit more by adding another Listbox and another array placed after the style:

   1: <Window.Resources>
   2: 
   3:         <x:Array x:Key="List" Type="{x:Type sys:String}">
   4:             <sys:String>A</sys:String>
   5:             <sys:String>B</sys:String>
   6:             <sys:String>C</sys:String>
   7:             <sys:String>D</sys:String>
   8:             <sys:String>E</sys:String>
   9:         </x:Array>
  10: 
  11:         <Style TargetType="ListBox">
  12:             <Setter Property="HorizontalAlignment" Value="Center" />
  13:         </Style>
  14:
  15:         <x:Array x:Key="List2" Type="{x:Type sys:String}">
  16:             <sys:String>A</sys:String>
  17:             <sys:String>B</sys:String>
  18:             <sys:String>C</sys:String>
  19:             <sys:String>D</sys:String>
  20:             <sys:String>E</sys:String>
  21:         </x:Array>
  22:
  23:     </Window.Resources>
  24: 
  25:     <StackPanel>
  26:         <ListBox x:Name="LstBox"
  27:                  ItemsSource="{Binding Source={StaticResource List}}">
  28:         </ListBox>
  29:         <ListBox x:Name="LstBox2"
  30:                  ItemsSource="{Binding Source={StaticResource List2}}">
  31:         </ListBox>
  32:     </StackPanel>

What do you think was the result? Well surprise, surprise everything is OK:

Listbox Array Binding

I kept on going and moved both the Arrays after the Style and again nothing showed up. For the final test I tried changing the binding expression on one of the first Listbox  to be more explicit so it looked like this:

   1: <ListBox x:Name="LstBox"
   2:         ItemsSource="{Binding Path=Items,Source={StaticResource List}}">
   3:         </ListBox>

And there you go! The items appeared in the Listbox

ListBx Ecplicit Binding

The little dot at the bottom is the second ListBox.

Conclusion: Use Explicit Binding, it seems to be safer, or put static data in from of all the style in the resources (I have no idea why that works)

If anyone knows why putting the array in first works please comment

Amit.

Tags :

5 Responses to “A Bug in WPF Static Resources?”


  1. John Oxley

    Said on April 21, 2008 :

    It’s not a bug in WPF. In C# when you declare static variables the order DOES matter. You cannot do this:
    static int foo = bar * 2;
    static in bar = 5;

    Someone more intelligent than I will tell you why.

  2. Amit

    Said on April 21, 2008 :

    Hey John

    I dont think it is the same as the array and the style are not related. the Listbox is using them both. If we would make the analogy i would say it is more like this (as far as i get it):
    this would work:

    static int foo = 2;
    static in bar = 5;

    int i = foo*bar;

    where as this would not work

    static int bar = 5;
    static int foo = 2;

    int i = foo*bar;

    so it is still weird :)
    Amit

  3. brock

    Said on November 17, 2008 :

    I agree, it is a little strange — but it does make some sense… Consider how the parser *might* work. Let’s suppose it marches right down the XAML in the StaticResources.

    1) First thing it touches in the first example is a style. It styles an empty ListBox (because the bindings have not run yet, as the parser has not reached the x:Array node yet). Now suppose the Control size and location is also calculated at this time. You would rightly end up with a little bitty box w/o content.

    2) Next it arrives at the x:Array node and binds the array values into the ListBox. Supposing it has no events that invalidate the Control’s display surface during binding, it would never redraw the Control and stay as it was before binding. So you would have a ListBox that has a bunch of items in it, but still displays as a little bitty box. (That to me seems like a bug, but who knows — maybe it was a conscious decision to increase performance by not redrawing controls multiple times)

    It reminds me a bit of putting javascript in a tag at the end of the body tag vs. a function that is called from the body onload event. Calling code from the body’s onload event is the proper way to do it, but sometimes unreliable (as it is not fired until all contents are available — a large image can slow it down). Supposing that js contains validation code for form submission, it may never be run. But if you put it in a function in the script tag at the bottom of the form, it is guaranteed to run before the user has a chance to click the submit button.

    I’m not saying it’s good or a definitive answer — but it’s a possibility as to why things happen the way they do.

  4. Amit

    Said on November 17, 2008 :

    @ brock

    You have a point, but, I would still expect an Items Control to redraw it self once something changed in its data to be the default option unless specified otherwise.

1 Trackback(s)

  1. Apr 22, 2008: Dew Drop - April 22, 2008 | Alvin Ashcraft's Morning Dew

Post a Comment