Pergunta

I am writing a style for a custom control derived directly from Control. Visual Studio places the style for a "Custom Control (WPF)" in the Themes\generic.xaml file. My style contains an image which I can't get displayed, seems there's something special about how to set the Source for an image from within the generic.xaml file.

I managed to reproduce the issue with a simpler scenario. Create a "WPF Custom Control library" then add a style for buttons like so, in the themes\generic.xaml . Here's my complete generic.xaml:

<ResourceDictionary
   ...
   <Style TargetType="{x:Type Button}">
     <Setter Property="Content">
        <Setter.Value>
            <Image Source="SmallHandle.png"></Image>
        </Setter.Value>
     </Setter>
   </Style>
</ResourceDictionary>

After this I have create a UserControl (in the same project) containing just a button (for the sake of testing out the style) like so:

<UserControl x:Class="BlendControls.UserControl1"
         ...
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">   
    <Button/>
</UserControl>

I have added the SmallHandle.png in the root project directory, in the themes directory, I have added it also to the good old Resources page, tried changing the build action to resource, embedded resource, tried copying the image manually to the build directory, but to no effect. The image is never displayed.

This must be related to the generic.xaml file, because copying the entire style to the same file where the Button is placed works fine. That is, the following works as expected:

<UserControl x:Class="BlendControls.UserControl1"
         ...             
         d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
       <Style TargetType="{x:Type Button}">
           <Setter Property="Content">
               <Setter.Value>
                   <Image Source="SmallHandle.png"></Image>
               </Setter.Value>
           </Setter>
       </Style>
    </UserControl.Resources>
       <Button></Button>
</UserControl>

So, how should I set the Source of images from generic.xaml? Or alternatively, where should I put the styles/templates for custom controls?

---- Solution ----

As pointed out by Sheridan, I have to use the "full" pack URI notation as:

pack://application,,,/MyAssembly;components/SmallHandle.png

This looks strange to me, as the image is in the same assembly. Not sure, looks like I am referencing from outside the dll.

Foi útil?

Solução

There's nothing unusual about accessing an image in Generic.xaml, you're just not referencing it correctly. You can reference a resource file in the project assembly using this format:

<Image Source="/AssemblyName;component/Subfolder/SmallHandle.png" />

If your images are directly inside the project root (which is not recommended), then you can access them like this:

<Image Source="/AssemblyName;component/SmallHandle.png" />

If your images are in a folder in another project, then you can access it like this:

<Image Source="/ReferencedAssembly;component/Subfolder/SmallHandle.png" />

See the Pack URIs in WPF page on MSDN for more information.


UPDATE >>>

In .NET 4, the above Image.Source values would work. However, Microsoft made some horrible changes in .NET 4.5 that broke many different things and so in .NET 4.5, you'd need to use the full pack path like this:

<Image Source="pack://application:,,,/AssemblyName;component/Images/image_to_use.png">

Outras dicas

If you don't feel as though your generic.xaml is being picked up, you can reference it from your App.cs.xaml like this:

<App.Resources>
   <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="/MY.NAMESPACE;component/Themes/generic.xaml" />
   </ResourceDictionary.MergedDictionaries>
</App.Resources>

Your generic.xaml file should be marked as "Resource".

Also, your image file should be marked as "Resource".

Finally, reference your ImageSource like this:

<Image Source="Themes/IMAGE.png" />

or try

<Image Source="../Themes/IMAGE.png" />

Personally, I like to put my style templates in their own .xaml file, and reference them all as MergedDictionaries.

Typed base style in Themes\Generic style is automatically applied only to Custom Control.

If you need use typed based style in your user control you need add generic.xaml to user control resources.

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Themes/Generic.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

Also change Image Source URI to

<Image Source="pack://application:,,,/WpfCustomControlLibrary1;component/SmallHandle.png" /> 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top