RadContextMenu Items Icon not visible with dynamic binding

7 posts, 1 answers
  1. Muhammad Ummar
    Muhammad Ummar avatar
    26 posts
    Member since:
    Jul 2012

    Posted 27 Aug 2012 Link to this post

    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?



  2. Answer
    Rosen Vladimirov
    Admin
    Rosen Vladimirov avatar
    640 posts

    Posted 28 Aug 2012 Link to this post

    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.

  3. UI for WPF is Visual Studio 2017 Ready
  4. Muhammad Ummar
    Muhammad Ummar avatar
    26 posts
    Member since:
    Jul 2012

    Posted 29 Aug 2012 Link to this post

    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. :) 
  5. Rosen Vladimirov
    Admin
    Rosen Vladimirov avatar
    640 posts

    Posted 29 Aug 2012 Link to this post

    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.

  6. Muhammad Ummar
    Muhammad Ummar avatar
    26 posts
    Member since:
    Jul 2012

    Posted 29 Aug 2012 Link to this post

    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
  7. Rosen Vladimirov
    Admin
    Rosen Vladimirov avatar
    640 posts

    Posted 30 Aug 2012 Link to this post

    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.

  8. Muhammad Ummar
    Muhammad Ummar avatar
    26 posts
    Member since:
    Jul 2012

    Posted 31 Aug 2012 Link to this post

    Makes sense, Thanks for your time and support.

    Regards
    Ummar
Back to Top
UI for WPF is Visual Studio 2017 Ready