Hi

 

Here is a problem that one of my colleagues who is just starting to use WPF got himself into. He was working on an application that displays items using an ItemsControl and uses a DataTemplate. Inside the DataTemplate he used an Image. Here is the Xaml code:

 

   1: <Window.Resources>
   2:         <Image Source="Creek.jpg" x:Key="IMG"></Image>
   3:     </Window.Resources>
   4:     <Grid>
   5:         <ItemsControl ItemsSource="{Binding}">
   6:             <ItemsControl.ItemTemplate>
   7:                 <DataTemplate>
   8:                     <Border BorderThickness="2" BorderBrush="Black" 
   9:                             CornerRadius="3" MinHeight="10">
  10:                         <ContentControl Content="{StaticResource IMG}"/>
  11:                     </Border>
  12:                 </DataTemplate>
  13:             </ItemsControl.ItemTemplate>
  14:         </ItemsControl>
  15:     </Grid>

This is a much simpler example, but the principal is the same.

 

Can you see what was he doing wrong?

 

In the code behind I will create a list and use it as the DataContext:

   1: public Window1()
   2: {
   3:    InitializeComponent();
   4:    List<int> data = new List<int> { 1, 2, 3, 4 };
   5:    this.DataContext = data;
   6: }

You will expect to see a window with 4 Images, but this is what you get:

Bad Resource Usage

Only one image shows up and all the other templates are empty.

 

Can you see the problem now?

 

It took me some time to see it because the code was much more complex, but then I noticed that he used the Image class as a resource for the Image.

 

Image is a WPF Control and can only have one parent! This is why it only displayed at the last item of the list. This is similar to doing the following:

   1: Image m = new Image();
   2: Border b1 = new Border();
   3: Border b2 = new Border();
   4: b1.Child = m;
   5: b2.Child = m;

What would happen here? The following:

Illegal child exception

I was actually surprised that my friend did not get an Exception, I will definitely have to check why no exception was thrown.

To correct the problem all you have to do is to use Bitmap Image which is a C# Class and not a WPF Control. You should use an Image in the template and use the BitmapImage as its source:

   1: <Window.Resources>
   2:    <!--<Image Source="Creek.jpg" x:Key="IMG"></Image>-->
   3:    <BitmapImage UriSource="Creek.jpg" x:Key="BMP"></BitmapImage>
   4: </Window.Resources>    
   5: <Grid>
   6:    <ItemsControl ItemsSource="{Binding}">
   7:        <ItemsControl.ItemTemplate>
   8:            <DataTemplate>
   9:                <Border BorderThickness="2" BorderBrush="Black" 
  10:                        CornerRadius="3" MinHeight="10">
  11:                    <!--<ContentControl Content="{StaticResource IMG}"/>-->
  12:                    <Image Source="{StaticResource BMP}"></Image>
  13:                </Border>
  14:            </DataTemplate>
  15:        </ItemsControl.ItemTemplate>
  16:    </ItemsControl>
  17: </Grid>

The result:

Good Resource Usage

 

Exactly what we wanted.

 

If any of you have an idea as to why we did not get an exception I will be happy to hear it.

 

Amit

Tags :

9 Responses to “Don’t Use a WPF Control in Windows.Resource”


  1. Dirk

    Said on April 2, 2009 :

    Hi!

    Did you try the attribute x:shared=”false” for your image resource? I think that should help :)

  2. Daniel

    Said on April 2, 2009 :

    “If any of you have an idea as to why we did not get an exception I will be happy to hear it.”

    Do you have the options ticked in Visual Studio’s “Debug” -> “Exceptions” ?

  3. Maxim

    Said on April 3, 2009 :

    A few stuff I saw inside WPF is that some exceptions are thrown but catched by the framework and never thrown. Check the output window. I don’t have a lot of experience in WPF but it might be a hint.

  4. Amit

    Said on April 3, 2009 :

    @Dirk – Interesting, it did work. I have never used x:shared before, Thanks.

    @Daniel – It was checked, I think it like the Binding Error that does not thows exceptions but writes to the output window.

    @Maxim – I thought of that but nothing showed up in the output window.

  5. Jones

    Said on April 28, 2009 :

    Nice post…

  6. Vijay anand

    Said on February 19, 2010 :

    Useful post.
    I can find more interesting information in this site.
    I love this site. :)

  7. Vijay anand

    Said on February 19, 2010 :

    Nice information shared.
    Great stuff.
    Keep going your great work.

  8. victor

    Said on October 17, 2010 :

    Why you use element Image in the Resources? – I did not hear about that. Use ImageSource:

    pack://application:,,,/Resources/Images/Creek.jpg

  9. Andy

    Said on March 8, 2013 :

    Even easier, just add x:Shared=”False” to your control and it will work fine!

Post a Comment