Icon is not displaying through code in PopupMenu in SL4 BA

Dec 11, 2011 at 4:51 AM

PopupMenu doesn't display LeftIcon and RightIcon through code in Silverlight Business Application. Same works perfectly fine in Silverlight Application. I am dynamically creating Listbox with PopupMenuItem and binding it ot PopupMenu. I am also not understanding the way ImageSource property is assigned. In one SL BA it takes "../images/cut.png" and same doesn't work in another SL BA. It takes "images/cut.png". After doing much R & D I found that if i take a Listbox control with one PopupMenuItem in XAML, PopupMenu works through Code. Very Surprising.....but in Normal Silverlight Application there is no such issue, PopupMenu works absolutely fine through Code or XAML.

Would appreciate quick help. 

Thanks in Advance !!!

Coordinator
Dec 12, 2011 at 6:10 AM

It would help if you could send me some sample code so I can reproduce the issue over here. Is that possible?

Dec 12, 2011 at 8:03 AM

 

Style itemcontainer = App.Current.Resources["VerticalMenuItemContainerStyle1"] as Style;
            Style st = App.Current.Resources["MenuStyle1"] as Style;
            ListBox _Edit = new ListBox(){ Style = st, ItemContainerStyle = itemcontainer };
       
            string cut = "../images/cut.png";
            Uri imageUricut = new Uri(cut, UriKind.RelativeOrAbsolute);
            PopupMenuItem _cut = new PopupMenuItem();
            _cut.Header = "Cut";
            _cut.ImageSource =  new System.Windows.Media.Imaging.BitmapImage(imageUricut);
            _Edit.Items.Add(_cut);

   PopupMenuItem _copy = new PopupMenuItem();

 

	string copy = "../images/copy.png";
            Uri imageUricopy = new Uri(copy, UriKind.RelativeOrAbsolute);

 

            _copy.Header = "Copy";
            _copy.ImageSource =  new System.Windows.Media.Imaging.BitmapImage(imageUricopy);
            _Edit.Items.Add(_copy );
           
            PopupMenu pmMain = new PopupMenu(_Edit) { Orientation = MenuOrientationTypes.Bottom };
            pmMain.AddTrigger(TriggerTypes.Hover, mnuEdit);
If i write it in XAML it works and Icon is displayed in both type of application (Silverlight App and Silverlight Business application). Kindly note above code works in Silverlight Application but same doesn't work in Silverlight Business
Application.
 One very important observation that surprised me is that if i take a Listbox control in XAML with one PopupMenuItem, above code shows the Icon. I need to take a dummy Listbox 
with Height 0 then Icon is displayed but it dispalys only "cut.png" that is mentioned in _Dummy ListBox PopupMenuItem. If I add one more PopupMenuItem with image as "images/copy.png" above 
code shows the copy.png as well. I am fail to understand the behaviour. Kinly check and revert. 
Thanks.....

 

 

 <ListBox x:Name="_Dummy" Height="0" >          
 <my:PopupMenuItem Name="MenuTop" Header="^Top" ImageSource="images/cut.png"   Tag="OrientationTop" Click="MenuItem_Clicked" ShortcutKeyModifier1="Control" ShortcutKeyModifier2="Alt" ShortcutKey="W"/>   
</ListBox>    

 

 

Coordinator
Dec 12, 2011 at 9:23 AM
Edited Dec 13, 2011 at 1:30 PM

Have you tried adding the menu items using the pmMain.AddItem(...) method instead? That's the recommended way to do it actually(see sample code on homepage) and it requires less coding too.

Dec 12, 2011 at 11:40 AM

Yes, I tried the below code but it didn't work. Still image is not showing but same is working if i write it in XAML as shown below. Have you tried it in Silverlight Business Application because same code works in 

Silverlight application project. One interesting fact is that below C# Code dispalys the icon if i write XAML Code as well as shown below and use the same image as mentioned in the XAML PopupMenuItem. 

Please help..I am struggling with it since 3 days but couldn't fix it. I don't know what is the issue with Silverlight Business Application and SL4PopupMenu

C# Code: 

pmMain = new PopupMenu() { Orientation = MenuOrientationTypes.Bottom };   

        pmMain.AddTrigger(TriggerTypes.Hover, button1);         

  pmMain.AddItem("../images/callrulesicon.png", "MyMenu", "../images/button-blue.png", "", MenuItem_Clicked);          

 

XAML CODE:

 <my:PopupMenu x:Name="pm" Orientation="Bottom" HoverElements="button1" >                  

<ListBox>                     

  <my:PopupMenuItem Name="MenuBottom" Header="Bottom" ImageSource="../images/callrulesicon.png"   Tag="OrientationBottom" Click="MenuItem_Clicked" Shortcut="Ctrl+Alt+S" />                   

</ListBox>               

</my:PopupMenu>

Coordinator
Dec 13, 2011 at 12:26 PM

Ok thanks I got your sample project in my inbox.

First thing I tried is to create an Image control on the view and assign it an image Uri in XAML and as expected it did show up when I press F5.

But it didn't when assigned it through code. So I can confirm that this is more of a Silverlight issue itself. Well at least you know what you need to focus on now.

Coordinator
Dec 13, 2011 at 12:28 PM
Edited Dec 13, 2011 at 1:05 PM

Oops...sorry I spoke to quickly...it does work when assigned through code...so I'm taking back all that I just said!!!

Coordinator
Dec 13, 2011 at 1:02 PM
Edited Dec 13, 2011 at 1:09 PM

Hmm...if I place an image control in XAML for each image used in the menu then everything works fine again.

It seems that the images need to be referenced early during application load for them to be accessible in the menu.

I'll inquire on it later on and let you know when I come up with something but at least you're left with this quick workaround

till then.

Coordinator
Dec 13, 2011 at 3:22 PM
Edited Dec 13, 2011 at 3:24 PM

Alternatively if you want to avoid modifying your XAML you can add this extension to your code:

namespace SL4PopupMenu
{
    using System.Windows.Controls;
    using System;
    using System.Windows;
    public static class SL4PopupMenuExtensions
    {
        static Image _imageLoader;
 
        public static void SetImageLoader(this PopupMenu popupMenu, Image imageContainer)
        {
            _imageLoader = imageContainer;
        }
 
        public static PopupMenuItem AddItemEx(this PopupMenu menu, string iconUrl, string header, string tag, RoutedEventHandler clickHandler)
        {
            _imageLoader.Source = new System.Windows.Media.Imaging.BitmapImage(new Uri(iconUrl, UriKind.RelativeOrAbsolute));
            return menu.AddItem(iconUrl, header, null, clickHandler);
        }
    }
}

Usage:
    var image = new Image() { Visibility = System.Windows.Visibility.Collapsed };
    LayoutRoot.Children.Add(image);
 
    var pmMain = new PopupMenu();
    pmMain.SetImageLoader(image);
    pmMain.AddItemEx( "../images/button-blue.png""Menu2"null, MenuItem_Clicked);
    pmMain.AddItemEx("../images/callrulesicon.png""Menu2"null, MenuItem_Clicked);
 
    pmMain.AddTrigger(TriggerTypes.Hover, code);
Feel free to modify the extension according to your needs.

However it'd be great if someone comes up with a better solution.
Dec 14, 2011 at 8:24 AM

Thanks for your time and help. Yes, Adding all images to Layoutroot  solves the problem for time being but need to look for some better solution. Please let me know if you get any further update on this. As of now i am using this approach only, let see if we can come up with some more appropriate solution.

I am also doing R & D and if i find some resolution to this issue, will update you on the post.

Thank you once again. Your work is really appreciable.

 

 

Coordinator
Dec 15, 2011 at 1:04 PM
Edited Feb 27, 2012 at 1:12 AM

I still haven't found a clean solution to the problem and all I could to do is make the code behind approach a little less invasive by using the following static method:

public static void PreloadMenuImages(Image imageLoader)
{
    foreach (var item in PopupMenuManager.MenuTriggers
                                         .Select(mt => mt.PopupMenuBase).OfType<PopupMenu>()
                                         .SelectMany(m => m.Items).OfType<PopupMenuItem>())
    {
        imageLoader.Source = item.ImageSource;
        imageLoader.Source = item.ImageRightSource;
    }
}

To start with make sure you have a dummy Image control in your page named, say imgLoader, so that you can pass it as parameter in the new method.

Then simply call it once your menus have been generated. All it does is loop through every image in your menus and loads them in your app via the dummy image control.

Jun 26, 2012 at 8:15 AM
ZiadJ wrote:

I still haven't found a clean solution to the problem and all I could to do is make the code behind approach a little less invasive by using the following static method:

public static void PreloadMenuImages(Image imageLoader)
{
    foreach (var item in PopupMenuManager.MenuTriggers
                                         .Select(mt => mt.PopupMenuBase).OfType<PopupMenu>()
                                         .SelectMany(m => m.Items).OfType<PopupMenuItem>())
    {
        imageLoader.Source = item.ImageSource;
        imageLoader.Source = item.ImageRightSource;
    }
}

To start with make sure you have a dummy Image control in your page named, say imgLoader, so that you can pass it as parameter in the new method.

Then simply call it once your menus have been generated. All it does is loop through every image in your menus and loads them in your app via the dummy image control.


Hi Ziad,

Just want to inform you that above mentioned issue is not occuring in Silverlight 5. I have upgraded my project from SL4 to SL5 and now Icon is displayed through XAML and Code. I guess there is some issue with SL4  Business application.