WPF UserControls: Image disappears even with '

2020-07-10 10:36发布

问题:

I defined a style in a ResourceDictionary for a button with an image:

<Style x:Key="BotonIrAInicioStyle" TargetType="Button">
    <Setter Property="Margin" Value="0"/>
    <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight}"/>
    <Setter Property="Content">
        <Setter.Value>
            <Image Margin="2" Source="{StaticResource IconoDashboardBlanco}" MaxHeight="20" Stretch="Uniform"
                   RenderOptions.BitmapScalingMode="HighQuality"/>
        </Setter.Value>
    </Setter>
</Style>

The image source is defined in another ResourceDictionary in the same assembly, and marked as x:Shared="False":

<BitmapImage x:Key="IconoDashboardBlanco" x:Shared="False"
UriSource="pack://application:,,,/QualityFramework;component/Images/dashboard64X64.png"/>

Since the style will be used in a different assembly, I used the "pack://application:,,," notation to reference the image. The Build Action for the image is set to Resource (Do not copy to output directory).

In the main assembly I have two UserControls which display a button with identical style:

<Button DockPanel.Dock="Left" Style="{StaticResource BotonIrAInicioStyle}" Click="BotonIrAInicio_Click"/> (Click event has nothing to do with the problem)

PROBLEM:

I open UserControl A containing the button with the image and the image is displayed ok. Then I open UserControl B containing an identical button, image ok. I open UserControl A again, and the image is gone. Happens the same if I open UserControl B and then UserControl A, the last one "owns" the image.

I went everywhere and all the solutions point to the x:Shared="False", the URI notation and the Build Action... I applied all of them and the problem still happens. I also tried cleaning and rebuilding with no success.

What am I missing? Thanks!

PS: if I set the content of both buttons to the image directly it works ok, but the whole point of styling is to avoid exactly that!

回答1:

The problem is not the BitmapImage it's the content in the setter of the button - it's created once and thus has to "jump" between instances.

The easy, but not WPF-isque, solution is setting x:Shared="False" on the style.

The correct way is to use ControlTemplate or DataTemplate.

From your observations:

"if I set the content of both buttons to the image directly it works ok" - this is because to do that you create two different instances of Image object.

But, this: "the whole point of styling is to avoid exactly that!" is a misconception - styles are not meant to set the content of content controls, the content is dependent upon the context. If you have a visual that is repeating for all buttons (without dependency upon the content), it should reside in ControlTemplate for the button. If you have a visual that is dependent upon the content (but the content is not the visual) it should reside in DataTemplate.



回答2:

I had a similary problem, it is not exatly the same thing but just in case i give you my solution it may help some other people o:) I resolve it this way (in visual studio 2019, wpf application) :

put your images in your project in a folder Create an image in xaml and put your source At this point for me the images are displayed in the design window but not at the runetime Access to your image in your project with the solution explorer Select each image and open the property window Set "Generation action" to "Resource" and "Copy in the repository" To "always copy"

I have done that and i can see my images at runtime :)

PS : sorry for my english, i'm french