2

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

Community
  • 1
  • 1

1 Answers1

1

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"))
};
King King
  • 61,710
  • 16
  • 105
  • 130
  • Thanks for the reply. I have tried using your first suggestion (I've seen BeginInit and EndInit before so i figured that would work) but it still doesn't display the icons for me... I have tried changing the images to resource and using the link you mentioned but it is saying system cannot find file specified... I feel I'm doing something silly. – Benjamin Garwood-Evans Oct 28 '14 at 16:03
  • @BenjaminEvans try setting some Background based on your `BitmapImage`, normally if the file path is OK, the Background should be shown correctly. Also be sure you tried exactly my code, the problem is not just `BeginInit` and `EndInit`, it's also related to `CacheOption`. I in fact could reproduce your problem and trying this code does help solve it. – King King Oct 28 '14 at 16:10
  • added further edits (see 2 and 3). Using the image elsewhere seems to work – Benjamin Garwood-Evans Oct 29 '14 at 08:01
  • @BenjaminEvans I thought I could reproduce your problem but looks like what I reproduced was just similar to your actual issue. You can try creating a simple demo first (with just 1 ContextMenu of 1 MenuItem) and see if the code could work. All the code I posted was tested in such a simple demo, so not sure if there is anything mysteriously wrong on your side. – King King Oct 29 '14 at 08:53
  • 1
    I found out that your answer was indeed correct. But I had another issue in logic elsewhere which was re-initialising the menu object >.< thanks for your help – Benjamin Garwood-Evans Oct 29 '14 at 11:21