This is a migrated thread and some comments may be shown as answers.

RadContextMenu Items Icon not visible with dynamic binding

6 Answers 442 Views
ContextMenu
This is a migrated thread and some comments may be shown as answers.
Muhammad Ummar
Top achievements
Rank 1
Muhammad Ummar asked on 27 Aug 2012, 05:10 PM
I am having a problem displaying the context menu RadContextMenu with Icon, I am using dynamic binding to observable collection, which contains context menu items (Text and Icon), I am following this tutorial "Dynamic Binding", following is my XAML.

<Style x:Key="MenuItemStyle" TargetType="{x:Type telerik:RadMenuItem}">
                <Setter Property="Icon">
                    <Setter.Value>
                        <Image Source="{Binding IconPath, Converter={StaticResource pathtoimage}}" />
                    </Setter.Value>
                </Setter>
            </Style>
 
            <HierarchicalDataTemplate x:Key="MenuItemTemplate">
                <telerik:RadButton Content="{Binding Title}" HorizontalContentAlignment="Left" Background="Transparent" BorderBrush="Transparent" />
            </HierarchicalDataTemplate>

and following is the XAML of RadGridView, on which context menu is placed.

<telerik:RadGridView x:Name="myGridView" AutoGenerateColumns="False" ItemsSource="{Binding GridData}" VerticalAlignment="Top">
            <telerik:RadGridView.Columns>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Result}" Header="Result"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Category}" Header="Category"/>
            </telerik:RadGridView.Columns>
            <telerik:RadContextMenu.ContextMenu>
                <telerik:RadContextMenu ItemsSource="{Binding ContextMenuItems}" ItemContainerStyle="{StaticResource MenuItemStyle}" ItemTemplate="{StaticResource MenuItemTemplate}">                 
                </telerik:RadContextMenu>

View Model is as follows
class MainViewModel
    {
        private ObservableCollection<MenuItemObj> menuitems_;
        public ObservableCollection<MenuItemObj> ContextMenuItems
        {
            get
            {
                return menuitems_;
            }
            set
            {
                menuitems_ = value;
            }
        }
 
        private ObservableCollection<GridRowDataObj> griddata_;
        public ObservableCollection<GridRowDataObj> GridData
        {
            get
            {
                return griddata_;
            }
            set
            {
                griddata_ = value;
            }
        }
    }
 
    public class MenuItemObj
    {
        public string Title { get; set; }
        public string IconPath { get; set; }
    }
 
    public class GridRowDataObj
    {
        public string Result { set; get; }
        public string Category { set; get; }
    }

and setting DataContext as

//TODO
            ObservableCollection<GridRowDataObj> gd = new ObservableCollection<GridRowDataObj>();
            gd.Add(new GridRowDataObj() { Result = "Matric", Category = "SSC" });
            gd.Add(new GridRowDataObj() { Result = "FSc", Category = "HSSC" });
            gd.Add(new GridRowDataObj() { Result = "FA", Category = "HSSC" });
 
            //TODO
            ObservableCollection<MenuItemObj> mi = new ObservableCollection<MenuItemObj>();
            mi.Add(new MenuItemObj() { Title = "My Item 1", IconPath = "/Images/item1.png" });
            mi.Add(new MenuItemObj() { Title = "My Item 2", IconPath = "/Images/item2.png" });
            mi.Add(new MenuItemObj() { Title = "My Item 3", IconPath = "/Images/item3.png" });
 
            MainViewModel mvm = new MainViewModel();
            mvm.ContextMenuItems = mi;
            mvm.GridData = gd;
 
            this.DataContext = mvm;

What I am getting is like this as in attached file "Menu_Image.png"

I am not sure why the icons for first and second menu items are not displayed, I have checked that the icon is displayed for last menu item only. I have complete project replicating this scenario, I can send you if required, Please help me out?



6 Answers, 1 is accepted

Sort by
0
Accepted
Rosen Vladimirov
Telerik team
answered on 28 Aug 2012, 02:51 PM
Hi,

We suggest you to use the code below - it is the correct way of implementing this scenario. There's no need to use the HierarchicalDataTemplate, you can just bind the Header in your ItemContainerStyle. Also you don't need the pathToImages Converter. Below you can see the correct way of Binding the Icon:
<Grid>
    <Grid.Resources>
        <Style x:Key="MenuItemStyle" TargetType="{x:Type telerik:RadMenuItem}">
            <Setter Property="Header" Value="{Binding Title}" />
            <Setter Property="Icon" Value="{Binding IconPath}" />
            <Setter Property="IconTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <Image Stretch="None" Source="{Binding}" />
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Grid.Resources>
         
    <telerik:RadGridView x:Name="myTextBox" AutoGenerateColumns="False" ItemsSource="{Binding GridData}" VerticalAlignment="Top">
        <telerik:RadGridView.Columns>
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Result}" Header="Result"/>
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Category}" Header="Category"/>
        </telerik:RadGridView.Columns>
                 
        <telerik:RadContextMenu.ContextMenu>
            <telerik:RadContextMenu x:Name="radContextMenu"
                                    ItemsSource="{Binding ContextMenuItems}"
                                    ItemContainerStyle="{StaticResource MenuItemStyle}">
            </telerik:RadContextMenu>
        </telerik:RadContextMenu.ContextMenu>
    </telerik:RadGridView>
</Grid>

We have tested this and it works fine, but if you face any problems, feel free to contact us.

Kind regards,
Rosen Vladimirov
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Muhammad Ummar
Top achievements
Rank 1
answered on 29 Aug 2012, 09:59 AM
thanks a lot a reply, it solved my problem, but I am still unsure why the icon was not displayed if we set it as

<Setter Property="Icon">
      <Setter.Value>
            <Image Source="{Binding pathtoimage, Converter={StaticResource pathtoimage}}" />
      </Setter.Value>
</Setter>

but if I set it like this

<Setter Property="Icon" Value="{Binding pathtoimage, Converter={StaticResource pathtoimage}}">
</Setter>

It worked properly, Ideally there shouldn't be any difference between the above two statements, It took lot of my time. :) 
0
Rosen Vladimirov
Telerik team
answered on 29 Aug 2012, 03:05 PM
Hi,

I tested both of the cases and I couldn't get it work. In fact I was very surprised the code below is compiled:
<Setter Property="Icon">
    <Setter.Value>
        <Image Source="{Binding pathtoimage, Converter={StaticResource pathtoimage}}" />
    </Setter.Value>
</Setter>

The problem with the image is that it is a UIElement. Such an object is created only once when the style is put together during Xaml parsing. The problem is that each UIElement instance can appear only once in the VisualTree. This was solved by using a template. This way each menu item receives a DataTemplate which is rendering the Image resource and creating a new instance in the VisualTree.

For the second code:
<Setter Property="Icon" Value="{Binding pathtoimage, Converter={StaticResource pathtoimage}}">
</Setter>

When I tested it, without explicitly setting the ItemTemplate as in my previous mail, I couldn't get it work - I received only the path to images set on Icon's position in the GUI.

But it doesn't matter, as I described above the problem is with the instances of the object in the VisualTree. You should always use Templates when you set the Icons' images in a Style.

Hopefully this answers your questions.

All the best,
Rosen Vladimirov
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Muhammad Ummar
Top achievements
Rank 1
answered on 30 Aug 2012, 04:52 AM
Hello Rosen,

Thanks for your clarification, first of all let me correct one of my mistake in my previous reply, The converter I am using a little bit changed

public class ResourceKeyToMenuIconConverter : IValueConverter
   {
       public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
       {
           try
           {
               if(value!=null)
               {
 
                   return new System.Windows.Controls.Image
                   {
                       Source = new BitmapImage(new Uri(value.ToString(), UriKind.Relative))
                   };
 
               }
           }
           catch (Exception e)
           {
               Console.WriteLine(e.Message);
               return null;
           }
           return null;
       }
 
       public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
       {
           throw new NotImplementedException();
       }
   }

and when you will use it like

<Setter Property="Icon" Value="{Binding pathtoimage, Converter={StaticResource resourcekeytomenuiconconverter}}">
</Setter>

It will work. and the UIElement rendering you have elaborated does make sense, but the above version is working without IconTemplate, and Icon is of type ContentPresenter which is also a UIElement

System.Object
  System.Windows.Threading.DispatcherObject
    System.Windows.DependencyObject
      System.Windows.Media.Visual
        System.Windows.UIElement
          System.Windows.FrameworkElement
            System.Windows.Controls.ContentPresenter

Please correct me if I am wrong?

Thanks for your help.
Best Regards
Ummar
0
Rosen Vladimirov
Telerik team
answered on 30 Aug 2012, 03:01 PM
Hi,

In your case the ContentPresenter is creating a separate image for all of your items and as all items have their own content presenter, you are able to see all of your images.
In the other case the Style is creating the Image, but it is only one image resource, which can be used by only one item and the practice is "The last one wins", so only your last menu item gets the image.

Hopefully this clears out the problem.

All the best,
Rosen Vladimirov
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Muhammad Ummar
Top achievements
Rank 1
answered on 31 Aug 2012, 07:57 AM
Makes sense, Thanks for your time and support.

Regards
Ummar
Tags
ContextMenu
Asked by
Muhammad Ummar
Top achievements
Rank 1
Answers by
Rosen Vladimirov
Telerik team
Muhammad Ummar
Top achievements
Rank 1
Share this question
or