Setting a MenuItem.Icon to an image not working

I am trying to dynamically populate a Menu in code and set its icon in c#.

I have read this post here and the answer given seems perfectly reasonable:

WPF setting a MenuItem.Icon in code

My interpretation:

mItem.Icon = new Image                       
{
    //filename is just image.png in build output folder
    Source = new BitmapImage(new Uri(fileName, UriKind.Relative)) 
}; 

but when it comes to run-time, the icons aren't there. Upon inspecting the data in the WPF visualiser, it says the ActualHeight and ActualWidth of the image are 0 and it doesn't look initialised (thas's to say, IsInitialized and IsLoaded are false).

I'd wager that I'm making some kind of rookie mistake somewhere but I'm just not seeing it (for the record, every other aspect of the menu is working as expected)

Thanks in advance :)

Edit 1: At the moment, the image is just a placeholder for testing which I have added as a link to the project then set the 'build action' to 'none' and the 'copy to output directory' to 'copy if newer'. The image is called "buttonIndicator_off.png" and the filename string at runtime is "buttonIndicator_off.png"

Edit 2: also tried this:

var bm = new BitmapImage();
bm.BeginInit();
bm.CacheOption = BitmapCacheOption.OnLoad;
bm.UriSource = new Uri(fileName, UriKind.Relative);
bm.EndInit();
mItem.Icon = new Image {
    Source = bm
}; 

and setting the images to compile as a resource and using:

mItem.Icon = new Image 
{
    Source = new BitmapImage( new Uri("pack://application:,,,/buttonIndicator_off.png"))
};

I'm almost certain all these solutions should work so I'm starting to think something odd is happening.

Edit 3: tested image with a rectangle fill:

rectangle_testImage.Fill = new ImageBrush(bm);

and this works

Upvotes: 2

Views: 2033

Answers (1)

King King
King King

Reputation: 63317

After some attempts, I've successfully made it work. The problem is you have to set the CacheOption to BitmapCacheOption.OnLoad. The important thing is we have to place all the initializing code in between the BeginInit() and EndInit() calls:

var bm = new BitmapImage();
bm.BeginInit();
bm.CacheOption = BitmapCacheOption.OnLoad;
bm.UriSource = new Uri(fileName, UriKind.Relative);
bm.EndInit();
mItem.Icon = new Image {
  Source = bm
}; 

A special thing is if you try setting some Background to some ImageBrush initializing from your BitmapImage, we don't need any steps above. (Just using one constructor call with the Uri passed in).

Also when embedding your image as a Resource (instead of None), you can try this code instead:

mItem.Icon = new Image {
  Source = new BitmapImage(
                new Uri("pack://application:,,,/buttonIndicator_off.png"))
};

Upvotes: 1

Related Questions