2

I have a button on a custom control and I'm trying to display an image on it which is defined as a resource in my App.xaml file like so:

<Application.Resources>
    <BitmapImage x:Key="PlusSymbol" UriSource="Resources/PlusSymbol.png" />
</Application.Resources>

For some reason I can't use this as a static resource within my custom control's template defined in the Themes\Generic.xaml file, it crashes my application during runtime saying that it cannot find the requested resource. Here's the xaml code I'm using to bind to the resource:

<Button Grid.Row="0" Grid.Column="1" Margin="3">
     <Image Source="{StaticResource PlusSymbol}"/>
</Button>

It DOES work during runtime if I define the resource the exact same way but within the Generic.xaml file, however it gives me a pre-compiler warning that it can't find the file since it's now looking for it in Themes/Resources/ rather than just in /Resources/. So I get a warning during design time but it works fine in runtime.

So why can't it find my resource when it's defined in App.xaml? I do this the exact same way in a regular WPF project and it works flawlessly, but in this custom control library it is giving me headaches. Any help is much appreciated!

StuartMorgan
  • 658
  • 5
  • 28

2 Answers2

2

This should work if you switch your StaticResource to DynamicResource so that the resource will be evaluated dynamically at runtime rather than statically. If you switch to DynamicResource.

<Button Grid.Row="0" Grid.Column="1" Margin="3">
   <Image Source="{DynamicResource PlusSymbol}"/>
</Button>

I believe this is because of how theme-based styles and templates are handled, as opposed to standard resources. This answer and this answer speak specifically to Generic.xaml and how it is different from other ResourceDictionaries.

Community
  • 1
  • 1
Brian S
  • 5,675
  • 1
  • 22
  • 22
  • I tried this, I no longer get the crash but the image is not showing up on the button. – StuartMorgan Feb 28 '13 at 18:51
  • If that's the case, then it sounds like WPF can't find the image. Make sure that the `BuildAction` on the image is set to Resource or EmbeddedResource (not Content). If you add the `Image` to a different screen in your app (without involving generic.xaml) does it show up there? – Brian S Feb 28 '13 at 18:59
  • Well in my main UI project I can use images that are specified in the App.xaml of that main UI project, but I'm now trying to do basically the same thing but in a custom control library. From what I can tell it looks like the Generic.xaml file in my custom control library cannot see the resources defined in the App.xaml file of the custom control library. – StuartMorgan Mar 04 '13 at 16:59
1

So the way I ended up getting this to work was by defining the BitmapImage in the Generic.xaml file and using a Pack URI to get to the file (here's the MSDN article about Pack URIs, which frankly just confused me). This way it's using a relative path to the file, and specifying the assembly that it's coming from (the file is located at \Resources\PlusSymbol.png in the MyCustomControlLibrary project and has a build action of Resource):

<BitmapImage x:Key="PlusSymbol" UriSource="pack://application:,,,/MyCustomControlLibrary;component/Resources/PlusSymbol.png" />

Then in the control template in Generic.xaml I use the resource like so:

<Button Grid.Row="0" Grid.Column="1" Margin="3" Height="25" Width="25" 
      <Image Source="{StaticResource PlusSymbol}"/>
</Button>

Note that I got fooled thinking that I could use the shorter version of the Pack URI like so:

<BitmapImage x:Key="PlusSymbol" UriSource="pack://application:,,,/Resources/PlusSymbol.png" />

However this was still causing the program to crash at runtime. I think the fact that this is a custom control library, and that the end consumer of the image is my UI project, makes the longer version which specifies the assembly that actually contains the image necessary.

Hope that helps anyone else who is having similar problems.

Note I don't think this technically answers my original question which specified using app-level resources (aka defined in the custom control library's App.xaml file) from Generic.xaml. Defining the PlusSymbol resource there still crashes the program. However I didn't actually care about doing it in App.xaml, I was just trying to get it to work right at both design time and run time. This solution does the trick for me, is fairly simple, and from what I can tell from my research is the best practice.

StuartMorgan
  • 658
  • 5
  • 28