How can I have Header Context Menu and Row Context Menu together in RADGridView

23 posts, 0 answers
  1. Sanket Singhvi
    Sanket Singhvi avatar
    20 posts
    Member since:
    May 2010

    Posted 16 Aug 2010 Link to this post

    I need separate context menu for Header and Rows. not able to find way to do it. Please provide an example.

    Regards
    Sanket
  2. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 17 Aug 2010 Link to this post

    Hi Sanket Singhvi,

    You can take a look at our demos where you will find examples both for adding context menus to the Rows and to the Headers. As the way they are appended is completely different and they are separate, there is no problem to create two distinct menus for single grid.
    So, following up the logic shown in the examples, the Header Context Menu can be created by adding an additional class - GridViewHeaderMenu and enabled in xaml through telerikGridViewHeaderMenu:GridViewHeaderMenu.IsEnabled="True". On the other hand the Row Context Menu is added directly in xaml:

    <telerik:RadContextMenu Opened="RadContextMenu_Opened" ItemClick="RadContextMenu_ItemClick">
         <telerik:RadContextMenu.Items>
                <telerik:RadMenuItem Header="Add" />
                <telerik:RadMenuItem Header="Edit" />
                <telerik:RadMenuItem Header="Delete" />
         </telerik:RadContextMenu.Items>
    </telerik:RadContextMenu>

    Furthermore, the Row Context Menu can be added to the grid on the RowLoaded event. 

    Kind regards,
    Maya
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. UI for WPF is Visual Studio 2017 Ready
  4. Sanket Singhvi
    Sanket Singhvi avatar
    20 posts
    Member since:
    May 2010

    Posted 17 Aug 2010 Link to this post

    Hi,

    I tried but it didn't work. It just crashed. Could you please provide a small project having both the features.

    Regards
    Sanket
  5. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 17 Aug 2010 Link to this post

    Hello Sanket Singhvi,

    The important thing here is that once you set the RowContextMenu, the HeaderContextMenu is overridden. 
    So, what you need to do is to implement your custom logic inside a custom separate class - ContextMenus for example. Basically, it would be the same as the one shown in our demo for HeaderContextMenu. However, in your class - ContextMenus, you will have to check if the element clicked is GridViewCell or GridViewHeaderCell. Afterwards, depending on the clicked item, you will create the context menu with different RadMenuItems.
    I am sending you a sample project illustrating the proposed solution.
     

    Sincerely yours,
    Maya
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  6. Ramyashree
    Ramyashree avatar
    29 posts
    Member since:
    Jan 2011

    Posted 21 Jan 2011 Link to this post

    Hi,

    I'm new to rad controls.... I'm not able to use RadContextMenu though it appears in the toolbox... If I try to add it in xaml, the following error is thrown.. Please let me know what needs to be done....

    Error:
    'The type 'telerik:RadContextMenu' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built. D:\Ramyashree\Country\Country\MainPage.xaml 92 26 Country'

    Thanks and Regds.,
    Ramya
  7. Miroslav Stantic
    Miroslav Stantic avatar
    42 posts
    Member since:
    Oct 2003

    Posted 07 Oct 2011 Link to this post

    Hi,

    Could you please where and what you had to change in order to accomplish this? I have lots of code already in place and do not understand what I needed to change.

    Thanks
    Miroslav
  8. Paul
    Paul avatar
    42 posts
    Member since:
    Jan 2012

    Posted 29 Mar 2013 Link to this post

    I reviewed the sample code but I'm afraid I find it deficient.  It seems that the GridVeiw is only capable of supporting a single context menu and the last one created wins.

    In the example code provided you are using the GridViewHeaderMenu and dynamically constructing a conext menu based upon cell type.  With a product having several grids this solution does not lend itself well.  Certainly one could use inheritance to inherit from teh GridViewHeaderMenu but at the end of the day there will still be a seperate class for each context menu.

    If the xaml is unremarked to allow the declarative ContextMenu then there is no context menu to the header.  How woud you duggest we keep the GridViewHeaderMenu agnostic of a standard GridRow context menu?

    I cannot update to version 2013.1 220 until an issue I reported with the GridView is resolved. Until then I am using 2012.3.1017 with an expectation to upgrade to 2013.4.x when it is released.  This is still relevant to 2012.3.1017.

    Thanks
    Paul
  9. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 03 Apr 2013 Link to this post

    Hi Paul,

    Generally, if you have different grids, all you need to do is to attach the behavior for creating a context menus. Do you have any troubles with the implementation or incorrect functionality ?

    Kind regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  10. Paul
    Paul avatar
    42 posts
    Member since:
    Jan 2012

    Posted 04 Apr 2013 Link to this post

    The main issue I have is within a single gird.  I would like to continue to use the GridViewHeaderMenu that you have in your examples but I need an entirely different menu for the rows.  Yes, I could create a behavior for the grid as suggested in this thread which will construct a menu in a class.  However, the row context menu has composite controls as MenuItems.  These controls have DependancyProperties which I am databinding to in my xaml. 

    Thanks

    Paul
  11. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 05 Apr 2013 Link to this post

    Hello Paul,

    In this case, what you can try is to create your context menu as a resource for example or as a new control and open it once you clicked on a row. Still, you could try handling MouseRightButton event instead, verify what is the element you clicked on and open the menu you want.
    It could be something like follows:

    public class GridViewHeaderMenu
        {
            // The logic here is the same as the one from the sample project attached above.
     
            private void Attach()
            {
                if (this.grid != null)
                {
                    this.grid.MouseRightButtonDown += new System.Windows.Input.MouseButtonEventHandler(OnMouseRightButtonDown);
                }
            }
     
            void OnMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
            {
                var clickedElement = e.OriginalSource as FrameworkElement;
                if (clickedElement.ParentOfType<GridViewHeaderCell>() != null)
                {
                    var menu = new RadContextMenu();
                    menu.Items.Add(new RadMenuItem() { Header = "HeaderMenu" });
                    menu.IsOpen = true;
                }
                else if (clickedElement.ParentOfType<GridViewCell>() != null)
                {
                    var menu = Application.Current.Resources["RowContextMenu"] as RadContextMenu;
                    menu.IsOpen = true;
                }
            }
        }

    In this case the menu is declared in the Resources section of the App. However, you can do that wherever appropriate for your scenario and get it here.
    Will that approach meet your requirements ?  

    Regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  12. Paul
    Paul avatar
    42 posts
    Member since:
    Jan 2012

    Posted 17 Apr 2013 Link to this post

    Can you show how you would do this with the GridViewHeaderMenu.cs that you have in other examples?  I would like to maintain one copy of this class and becasue it is designed to be referenced in the XAML, with the DependancyProperty for IsEnabled, it is not going in very well.

    For the row conetxt menu I will try your suggestion of the resource.

    Thank you
  13. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 19 Apr 2013 Link to this post

    Hi Paul,

    Could you clafity a bit ? Do you want to have context menu defined in the resources and use it for the header ?  

    Greetings,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  14. Paul
    Paul avatar
    42 posts
    Member since:
    Jan 2012

    Posted 19 Apr 2013 Link to this post

    Sure, I already use a class based upon your example of a header context menu.  This is using a DependancyProperty and is designed to be referenced declaratively.  Using your suggestion I would call it from the C# code but because how it is designed it does not function in this manor.  I don't want to discard it and replace it with a design not intended to be used in the declarative code because it is used elsewhere.  I also don't want to create a new version of that specifically for the C# code because then I two sets of code doing the same thing to keep synchronized.

    Does this help?

    Thank you

    Paul
  15. Nick
    Admin
    Nick avatar
    593 posts

    Posted 24 Apr 2013 Link to this post

    Hello Paul,

    The same approach that Maya suggested can be used for the HeaderCell as well. The only thing you have to do is define the HeaderContextMenu structure in your resources, after that it is all analogical. 

    Do you have any problems achieving that? 


    Kind regards,
    Nikolay Vasilev
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  16. Paul
    Paul avatar
    42 posts
    Member since:
    Jan 2012

    Posted 02 May 2013 Link to this post

    Thank you. 

    We are very close but I am facing one problem from this.  Related to ticket 676477, the Grid takes focus when teh context menu is closed.  I was getting around this with the declarative mechanism because I had a reference in the code behind to a UserControl that the context menu is opening.  On the Dispatcher I was setting focus to the subsequent control so a control hosted in a PopUp invoked by my UserControl could have focus.  I have the following inplace in the context menu which is getting called:
    RoutedEventArgs routedEventArgs = new RoutedEventArgs(MyContextMenu.ContextMenuClosed);
    RaiseEvent(routedEventArgs);

    and in the XAML:
    <telerik:RadGridView my:MyContextMenu.IsEnabled="True" my:MyContextMenu.ContextMenuClosed="GridContextMenu_Closed"

    Since the XAML does not have an issue with the ContextMenuClosed event I know the event is proeprly registered.  It looks as if the context menu is created twice, as I put a break point on the constructor.   How can the event be raised on the same instance that is being set IsEnabled="True"?

    Thank you
    Paul
  17. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 07 May 2013 Link to this post

    Hi Paul,

    I believe I am missing something here. Could you clarify what the problem is ? Do you want an event to be raised for an context menu instance that is not enabled ? How are both menus related ?
    Will it be possible to update the project attached above or the one from the other ticket (676477) and send it back so that I can see your exact settings and the issue you are struggling with ? 

    All the best,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  18. Paul
    Paul avatar
    42 posts
    Member since:
    Jan 2012

    Posted 13 May 2013 Link to this post

    I created 692704 to unclude the sample application.

    Thanks

    Paul
  19. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 14 May 2013 Link to this post

    Hi Paul,

    Thanks for the project. My recommendation would be to run through this article on how to create an attached event and if possible, try to keep the logic inside the menu class rahter than exposing it in the code-behind.
    Let me know in case you have any further troubles. 

    Regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  20. Nargis
    Nargis avatar
    8 posts
    Member since:
    Aug 2014

    Posted 21 Oct 2014 Link to this post

    Hi Maya,

    I have the same issue and need the context menu for the grid header, grid row and grid child row. I modified your sample project so far, that I take the dependency property ContextMenuProperty instead of creating new context by clicking. My problem is that the content of the context menu appears either on parent grid row or on child grid row, depending on where I clicked first. However, the content should be displayed for both the parent grid row and the child grid row for.

    Here is my code:
    MainWindow.xaml
    <Window.Resources>
            <my:MyViewModel x:Key="MyViewModel"/>
        </Window.Resources>
        <Grid DataContext="{StaticResource MyViewModel}">
            <telerik:RadGridView Name="playersGrid"  ColumnWidth="*"
                                         my:GridViewHeaderMenu.IsEnabled="True"
                                         my:GridViewHeaderMenu.RowContextMenu="{Binding PositionContextMenu}"
                                         ItemsSource="{Binding Clubs}"
                                         SelectedItem="{Binding SelectedItem}"
                                         AutoGenerateColumns="False">
                <telerik:RadGridView.Columns>
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding Name}"/>
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding Established}"
                                                Header="Est."
                                                DataFormatString="{}{0:yyyy}"/>
                    <telerik:GridViewDataColumn DataMemberBinding="{Binding StadiumCapacity}"
                                                Header="Stadium"
                                                DataFormatString="{}{0:N0}"/>
                </telerik:RadGridView.Columns>
                <telerik:RadGridView.ChildTableDefinitions>
                    <telerik:GridViewTableDefinition/>
                </telerik:RadGridView.ChildTableDefinitions>
                <telerik:RadGridView.HierarchyChildTemplate>
                    <DataTemplate>
                        <telerik:RadGridView Name="playersGrid"
                                         ItemsSource="{Binding Players}"
                                         AutoGenerateColumns="False"
                                         my:GridViewHeaderMenu.IsEnabled="True"
                                         my:GridViewHeaderMenu.RowContextMenu="{Binding Path=DataContext.PositionContextMenu,
                                                                                RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type my:MainWindow}}}">
                            <telerik:RadGridView.Columns>
                                <telerik:GridViewDataColumn DataMemberBinding="{Binding Name}"/>
                                <telerik:GridViewDataColumn DataMemberBinding="{Binding Number}"/>
                                <telerik:GridViewDataColumn DataMemberBinding="{Binding Position}"/>
                                <telerik:GridViewDataColumn DataMemberBinding="{Binding Country}"/>
                            </telerik:RadGridView.Columns>
                        </telerik:RadGridView>
                    </DataTemplate>
                </telerik:RadGridView.HierarchyChildTemplate>
            </telerik:RadGridView>
        </Grid>
    MyViewModel.cs
    public class MyViewModel : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
     
            private ObservableCollection<Club> clubs;
            private ObservableCollection<Player> players;
            private object selectedItem;
     
     
            private Telerik.Windows.Controls.RadContextMenu _positionsContextMenu;
            public Telerik.Windows.Controls.RadContextMenu PositionContextMenu
            {
                get {return _positionsContextMenu;}
                set
                {
                    _positionsContextMenu = value;
                    this.OnPropertyChanged("PositionContextMenu");
                }
            }
     
            public MyViewModel()
            {
                InitPositionsContextMenu();
            }
     
            private void InitPositionsContextMenu()
            {
                PositionContextMenu = new Telerik.Windows.Controls.RadContextMenu();
                PositionContextMenu.Items.Add(new RadMenuItem() { Header ="Add"});
                PositionContextMenu.Items.Add(new RadMenuItem() { Header ="Edit"});
                PositionContextMenu.Items.Add(new RadMenuItem() { Header ="Delete"});
            }
    ...
    }

    GridViewHeaderMenu.cs

    ....
    public static readonly DependencyProperty RowContexMenuProperty
              = DependencyProperty.RegisterAttached("RowContextMenu", typeof(RadContextMenu), typeof(GridViewHeaderMenu),
                  new PropertyMetadata(new PropertyChangedCallback(OnRowContextMenuPropertyChanged)));
     
            public static void SetRowContextMenu(DependencyObject dependencyObject, RadContextMenu value)
            {
                dependencyObject.SetValue(RowContexMenuProperty, value);
            }
     
            public static RadContextMenu GetRowContextMenu(DependencyObject dependencyObject)
            {
                return dependencyObject.GetValue(RowContexMenuProperty) as RadContextMenu;
            }
     
            private static void OnRowContextMenuPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
            {
                SetRowContextMenu(dependencyObject, (RadContextMenu)e.NewValue);
            }
     
    void OnMenuOpened(object sender, RoutedEventArgs e)
            {
                RadContextMenu menu = (RadContextMenu)sender;
                GridViewHeaderCell cell = menu.GetClickedElement<GridViewHeaderCell>();
                GridViewCell gridCell = menu.GetClickedElement<GridViewCell>();
                 
                if (cell != null)
                {
                    menu.Items.Clear();
     
                    RadMenuItem item = new RadMenuItem();
                    item.Header = "Header Context Menu";
                    menu.Items.Add(item);
     
                }
                else if(gridCell != null)
                {              
                    menu.Items.Clear();
                     
                    RadMenuItem item = new RadMenuItem();
                    RadContextMenu rowMenu = gridCell.ParentRow.ParentOfType<RadGridView>().GetValue(RowContexMenuProperty) as RadContextMenu;
                     
                    //item.Header = "Row Context Menu";
                    //menu.Items.Add(rowMenu);
                    AddMenuItems(menu, rowMenu);
                     
                }
                else
                {
                    menu.IsOpen = false;
                }
            }
     
     private readonly List<RadMenuItem> _rowItems = new List<RadMenuItem>();
            private void AddMenuItems(RadContextMenu menu, RadContextMenu clickedElementMenu)
            {
                if (clickedElementMenu != null)
                {
                    menu.Items.Clear();
                    if (clickedElementMenu.Items.Count > 0)
                    {
                        List<RadMenuItem> menuitems = new List<RadMenuItem>();
                        foreach (var item in clickedElementMenu.Items)
                        {
                            menuitems.Add(item as RadMenuItem);
                        }
                        foreach (RadMenuItem item in menuitems)
                        {
                            clickedElementMenu.Items.Remove(item);
                            if (_rowItems.Contains(item) == false)
                            {
                                _rowItems.Add(item);
                            }
                        }
                    }
                    if (_rowItems.Count > 0)
                    {
                        foreach (var item in _rowItems)
                        {
                            menu.Items.Add(item);
                        }
                    }
                }
                else
                {
                    menu.IsOpen = false;
                }
            }
    ...

    Could you tell me what am I missing?
    Thank you a lot in advance!
    Best regards
    Nargis
  21. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 23 Oct 2014 Link to this post

    Hello Nargis,

    I tested the code you provided and actually, the menu does not open in the child grid on my side. Please make sure that the menu is not null. Why don't you create the menu inside the GridViewHeaderMenu class and use it there rather than placing visual element in your ViewModel ?



    Regards,
    Maya
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  22. Nargis
    Nargis avatar
    8 posts
    Member since:
    Aug 2014

    Posted 23 Oct 2014 in reply to Maya Link to this post

    Hello Maya,

    that is my problem. If I click with mouse left button on parent grid row first the menu appears always only in the parent grid row and never on child grind row. After restarting the application if I click with mouse left button on child grid row first the menu appears always only in the child grid row and never on parent grind row.
    I must take dependency Property because I use GridViewHeaderMenu-class for different ViewModels with different context menu.

    Do you have any idea why the context menu for the second-clicked grid is always empty.
    Thank you a lot!
    Best regards
    Nargis
  23. Nargis
    Nargis avatar
    8 posts
    Member since:
    Aug 2014

    Posted 27 Oct 2014 Link to this post

    Hello again,

    The behavior, that I have explained in the preview post, I get If I add the following code snippet in the method OnMenuOpened(), in the line numbers 15-18. I missed to add this code in the post preview. I apologize for that.

    01.void OnMenuOpened(object sender, RoutedEventArgs e)
    02.        {
    03.            ...
    04.            if (cell != null)
    05.            {
    06.                ...
    07. 
    08.            }
    09.            else if(gridCell != null)
    10.            {              
    11.                menu.Items.Clear();
    12.                 
    13.                RadMenuItem item = new RadMenuItem();
    14.                RadContextMenu rowMenu = gridCell.ParentRow.ParentOfType<RadGridView>().GetValue(RowContextMenuProperty) as RadContextMenu;
    15.                if (rowMenu == null)
    16.                {
    17.                    rowMenu = ((Telerik.Windows.Controls.GridView.GridViewDataControl)(gridCell.ParentRow.ParentOfType<RadGridView>())).ParentRow.ParentOfType<RadGridView>().GetValue(RowContextMenuProperty) as RadContextMenu;
    18.                }
    19.                //item.Header = "Row Context Menu";
    20.                //menu.Items.Add(rowMenu);
    21.                AddMenuItems(menu, rowMenu);
    22.                 
    23.            }
    24.            else
    25.            {
    26.                menu.IsOpen = false;
    27.            }
    28.        }

    I hope you have any tip for my problem.
    Thank you a lot!
    Best regards
    Nargis
  24. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 28 Oct 2014 Link to this post

    Hello Nargis,

    The context menu is initialized only once in the ViewModel and not for every RadGridView instance. Then what happens is that you trigger OnMenuOpen, the code pass through - rowMenu == null, initializes it and then in AddMenuItems method you clear the items from the initial instance of RowContextMenu:
    foreach (RadMenuItem item in menuitems)
                       {
                           clickedElementMenu.Items.Remove(item);
                           if (_rowItems.Contains(item) == false)
                           {
                               _rowItems.Add(item);
                           }
                       }


    Then when the menu for the inner grid should be created, the code passes through menu == null, initializes new instance, but then " if (clickedElementMenu.Items.Count > 0) " returns false since you already cleared the items when you created the context menu for the previous grid. 
    So, you need to modify the logic so that it corresponds to your requirements, but without clearing the information of the items. 


    Regards,
    Maya
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
Back to Top
UI for WPF is Visual Studio 2017 Ready