Context Menu in DataGridColumnHeader

5 posts, 0 answers
  1. Ramesh Subramanian
    Ramesh Subramanian avatar
    2 posts
    Member since:
    Nov 2009

    Posted 28 Nov 2009 Link to this post

    I am trying to have a context menu, in SL3 DataGrid Header similar to the one you guys have put up for GridView. Since DataGrid doesn't expose DataGridColumnHeader, I use the mouse enter event to espose the DataGridColumnHeader and initialize the Menu

     public class DataGridHeaderMenu 
        { 
            private DataGrid grid = null
            List<DataGridColumnHeader> headers = new List<DataGridColumnHeader>(); 
            public DataGridHeaderMenu(DataGrid grid) 
            { 
                this.grid = grid; 
            } 
     
            public static readonly DependencyProperty IsEnabledProperty 
                = DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(DataGridHeaderMenu), 
                    new PropertyMetadata(new PropertyChangedCallback(OnIsEnabledPropertyChanged))); 
     
            public static void SetIsEnabled(DependencyObject dependencyObject, bool enabled) 
            { 
                dependencyObject.SetValue(IsEnabledProperty, enabled); 
            } 
     
            public static bool GetIsEnabled(DependencyObject dependencyObject) 
            { 
                return (bool) dependencyObject.GetValue(IsEnabledProperty); 
            } 
     
            private static void OnIsEnabledPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
            { 
                DataGrid grid = dependencyObject as DataGrid; 
                if (grid != null) 
                { 
                    if ((bool) e.NewValue) 
                    { 
                        // Create new GridViewHeaderMenu and attach RowLoaded event. 
                        DataGridHeaderMenu menu = new DataGridHeaderMenu(grid); 
                        menu.Attach(); 
                    } 
                } 
            } 
     
            private void Attach() 
            { 
                if (grid != null) 
                { 
                    
                    this.grid.MouseEnter += new MouseEventHandler(grid_MouseEnter); 
                } 
            } 
     
            void grid_MouseEnter(object sender, MouseEventArgs e) 
            { 
                Point pt = e.GetPosition(this.grid); 
                var list = VisualTreeHelper.FindElementsInHostCoordinates(pt, this.grid); 
                foreach (UIElement elem in list) 
                { 
                    if (elem.GetType().Name == "DataGridColumnHeader") 
                    { 
                        if (headers.Count == 0) 
                        { 
                            headers.Add((DataGridColumnHeader)elem); 
                            InitializeMenus((DataGridColumnHeader)elem); 
                        } 
                        else 
                        { 
                            if(!headers.Contains((DataGridColumnHeader)elem)) 
                            { 
                                headers.Add((DataGridColumnHeader)elem); 
                                InitializeMenus((DataGridColumnHeader)elem); 
                            } 
                        } 
     
                        
     
                         
                    } 
                } 
            } 
     
            //void grid_Loaded(object sender, RoutedEventArgs e) 
            //{ 
            //    foreach (DataGridBoundColumn Column in this.grid.Columns) 
            //    { 
            //        if (Column != null) 
            //        { 
            //            InitializeMenus(Column); 
            //        } 
            //    } 
            //} 
     
            private void InitializeMenus(DataGridColumnHeader col) 
            { 
     
               
                RadContextMenu contextMenu = new RadContextMenu(); 
     
                RadMenuItem item = new RadMenuItem() { Header = String.Format(@"Sort Ascending by ""{0}""", col.Content.ToString()) }; 
                contextMenu.Items.Add(item); 
     
                contextMenu.EventName = "MouseRightButtonDown"
                 
                RadContextMenu.SetContextMenu(this.grid, contextMenu); 
                
                           
     
     
            } 
     
        } 

    But it doesn't have the desired behavior... the context menu appers very rarely... most times it doesn't appear at all. Can some one help me out
  2. Hristo
    Admin
    Hristo avatar
    832 posts

    Posted 30 Nov 2009 Link to this post

    Hello Ramesh Subramanian,

    The problem is in the code that attach the context menu. You are using MouseEnter event and it is fired once (when the mouse enter in the grid). At this moment is the mouse is over the DataGridColumnHeader then context menu works. But most of the time it is not and this is why it is not attaching the menu. The problem is that MouseEnter is fired only when you enter the grid and not while you are in it.
    As a workaround I can recommend you to use MouseMove event instead of MouseEnter.
    Let us know if you need more help.

    Best wishes,
    Hristo
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  3. DevCraft banner
  4. Ramesh Subramanian
    Ramesh Subramanian avatar
    2 posts
    Member since:
    Nov 2009

    Posted 30 Nov 2009 Link to this post

    Thanks for the reply.

    Finally I have been able to get the menu work properly.... using another workaround (though I haven't tried out your suggestion). I have attached the menu to the grid.  In the menu's opened event , and in it I am using  GetClickedElement() to get the column header

    DataGridColumnHeader columnHeader = (contextMenuClose).GetClickedElement<DataGridColumnHeader>(); 


    . And I close the menu attached to the data grid  It works well... I have been able to implement grouping, un- grouping, sorting for the columns  with no problems... the problem is when I try to implement hide/unhide columns. This to works well for the first few attempts

    But once I begin to bring the hidden columns back the binding seems to go haywire! (see screen shots).

    Here is the code:

    using System; 
    using System.Net; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Documents; 
    using System.Windows.Ink; 
    using System.Windows.Input; 
    using System.Windows.Media; 
    using System.Windows.Media.Animation; 
    using System.Windows.Shapes; 
    using Telerik.Windows.Controls; 
    using System.Windows.Controls.Primitives; 
    using System.Collections.Generic; 
    using System.Windows.Data; 
    using Telerik.Windows; 
    using System.Collections.ObjectModel; 
    using System.ComponentModel; 
    using System.Linq; 
     
    namespace Test 
        public class DataGridHeaderMenu 
        { 
            private DataGrid grid = null
            List<DataGridColumnHeader> headers = new List<DataGridColumnHeader>(); 
            public DataGridHeaderMenu(DataGrid grid) 
            { 
                this.grid = grid; 
            } 
     
            public static readonly DependencyProperty IsEnabledProperty 
                = DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(DataGridHeaderMenu), 
                    new System.Windows.PropertyMetadata(new PropertyChangedCallback(OnIsEnabledPropertyChanged))); 
     
            public static void SetIsEnabled(DependencyObject dependencyObject, bool enabled) 
            { 
                dependencyObject.SetValue(IsEnabledProperty, enabled); 
            } 
     
            public static bool GetIsEnabled(DependencyObject dependencyObject) 
            { 
                return (bool) dependencyObject.GetValue(IsEnabledProperty); 
            } 
     
            private static void OnIsEnabledPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
            { 
                DataGrid grid = dependencyObject as DataGrid; 
                if (grid != null) 
                { 
                    if ((bool) e.NewValue) 
                    { 
                        // Create new GridViewHeaderMenu and attach RowLoaded event. 
                        DataGridHeaderMenu menu = new DataGridHeaderMenu(grid); 
                        menu.Attach(); 
                    } 
                } 
            } 
     
            private void Attach() 
            { 
                if (grid != null) 
                { 
                    
                    //this.grid.MouseEnter += new MouseEventHandler(grid_MouseEnter); 
                    this.grid.Loaded += new RoutedEventHandler(grid_Loaded); 
                } 
            } 
     
            void grid_Loaded(object sender, RoutedEventArgs e) 
            { 
                RadContextMenu gridContextMenu = new RadContextMenu(); 
     
                gridContextMenu.EventName = "MouseRightButtonDown"
                RadContextMenu.SetContextMenu(grid, gridContextMenu); 
     
                gridContextMenu.Opened += new RoutedEventHandler(gridContextMenu_Opened); 
                
            } 
     
            void gridContextMenu_Opened(object sender, RoutedEventArgs e) 
            { 
                //Close Data grid Context Menu. 
                RadContextMenu contextMenuClose = sender as RadContextMenu; 
                contextMenuClose.IsOpen = false
                 
                //Get the Column Header  
                DataGridColumnHeader columnHeader = (contextMenuClose).GetClickedElement<DataGridColumnHeader>(); 
     
                //if Right click was made on column Header. 
                if (columnHeader != null) 
                { 
     
                     
                    RadContextMenu contextMenu = new RadContextMenu(); 
     
                    RadMenuItem item = new RadMenuItem() { Header = String.Format(@"Sort Ascending by ""{0}""", columnHeader.Content.ToString()),  
                                                           Tag = columnHeader.Content.ToString() }; 
                    contextMenu.Items.Add(item); 
     
                    item = new RadMenuItem() { Header = String.Format(@"Sort Descending by ""{0}""", columnHeader.Content.ToString()), 
                                                Tag = columnHeader.Content.ToString()}; 
                    contextMenu.Items.Add(item); 
     
                    item = new RadMenuItem() { Header = String.Format(@"Clear Sorting by ""{0}""", columnHeader.Content.ToString()), 
                                               Tag = columnHeader.Content.ToString() }; 
                    contextMenu.Items.Add(item); 
     
                    item = new RadMenuItem() { Header = String.Format(@"Group by ""{0}""", columnHeader.Content.ToString()), 
                                               Tag = columnHeader.Content.ToString()}; 
                    contextMenu.Items.Add(item); 
     
                    item = new RadMenuItem() { Header = String.Format(@"Ungroup ""{0}""", columnHeader.Content.ToString()),  
                                               Tag = columnHeader.Content.ToString() }; 
                    contextMenu.Items.Add(item); 
     
                    item = new RadMenuItem() { Header = "Choose Columns:" }; 
                    contextMenu.Items.Add(item); 
     
                                   
     
                    // create menu items 
                    foreach (DataGridColumn column in grid.Columns) 
                    { 
                        RadMenuItem subMenu = new RadMenuItem() 
                        { 
                            Header = column.Header, 
                            IsCheckable = true 
                             
                        }; 
     
                        // bind IsChecked menu item property to Visible column property 
                        subMenu.SetBinding(RadMenuItem.IsCheckedProperty, 
                            new Binding("Visibility") { Mode = BindingMode.TwoWay, Source = columnConverter = new VisibilityToBooleanConverter() }); 
                                            
                        subMenu.StaysOpenOnClick = true
     
                        BindingExpression expression = subMenu.GetBindingExpression(RadMenuItem.IsCheckedProperty); 
                        expression.UpdateSource(); 
     
                        item.Items.Add(subMenu); 
                    } 
                     
                    contextMenu.EventName = "MouseRightButtonDown"
                    RadContextMenu.SetContextMenu(columnHeader, contextMenu); 
     
                     
                    contextMenu.IsOpen = true
     
                    contextMenu.ItemClick += new RadRoutedEventHandler(contextMenu_ItemClick); 
                     
                } 
     
     
                 
     
                
            } 
     
            void contextMenu_ItemClick(object sender, RadRoutedEventArgs e) 
            { 
                RadContextMenu menu = (RadContextMenu)sender; 
                RadMenuItem clickedItem = ((RadRoutedEventArgs)e).OriginalSource as RadMenuItem; 
     
                if (clickedItem.Parent is RadMenuItem) 
                    return; 
     
                string header = Convert.ToString(clickedItem.Header); 
     
                PagedCollectionView gridSource = (PagedCollectionView) grid.ItemsSource; 
     
                SortDescription sd = (from d in gridSource.SortDescriptions 
                                      where d.PropertyName == clickedItem.Tag.ToString().Replace(" ", "") 
                                      select d).FirstOrDefault(); 
     
                if (header.Contains("Sort Ascending")) 
                { 
                    if (sd != null) 
                    { 
                        gridSource.SortDescriptions.Remove(sd); 
                    } 
     
                    gridSource.SortDescriptions.Add(new SortDescription() 
                    { 
                        PropertyName = clickedItem.Tag.ToString().Replace(" ", ""), 
                        Direction = ListSortDirection.Ascending 
                    }); 
                } 
                else if (header.Contains("Sort Descending")) 
                { 
                    if (sd != null) 
                    { 
                        gridSource.SortDescriptions.Remove(sd); 
                    } 
     
                    gridSource.SortDescriptions.Add(new SortDescription() 
                    { 
                        PropertyName = clickedItem.Tag.ToString().Replace(" ", ""), 
                        Direction = ListSortDirection.Descending 
                    }); 
                } 
                else if (header.Contains("Clear Sorting")) 
                { 
                    if (sd != null) 
                    { 
                        gridSource.SortDescriptions.Remove(sd); 
                    } 
     
                } 
                else if (header.Contains("Group by")) 
                { 
     
                    PropertyGroupDescription pgd = (PropertyGroupDescription)(from d in gridSource.GroupDescriptions 
                                                    where ((PropertyGroupDescription)d).PropertyName == clickedItem.Tag.ToString().Replace(" ", "") 
                                                    select d).FirstOrDefault(); 
     
                    if (pgd == null) 
                    { 
                                gridSource.GroupDescriptions.Add(new PropertyGroupDescription() 
                                { 
                                    PropertyName = clickedItem.Tag.ToString().Replace(" ", "") 
                                }); 
                    } 
                       
                        
                                     
                            
                                            
                } 
                else if (header.Contains("Ungroup")) 
                { 
     
                    PropertyGroupDescription pgd = (PropertyGroupDescription)(from d in gridSource.GroupDescriptions 
                                                    where ((PropertyGroupDescription)d).PropertyName == clickedItem.Tag.ToString().Replace(" ", "") 
                                                    select d).FirstOrDefault(); 
     
                        if (pgd != null) 
                        { 
                            gridSource.GroupDescriptions.Remove(pgd); 
                             
                        } 
           
     
     
     
     
                } 
                     
     
     
     
     
            } 
     
             
            
            
     
           
     
             
        } 
     









  5. Nikolay
    Admin
    Nikolay avatar
    3997 posts

    Posted 04 Dec 2009 Link to this post

    Hello Ramesh Subramanian,

    We will be looking into the code you provided and try to locate the source of the problem. We will follow up with you as soon as we have certain results.

    Best wishes,
    Nick
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  6. Hristo
    Admin
    Hristo avatar
    832 posts

    Posted 08 Dec 2009 Link to this post

    Hello Ramesh Subramanian,

    I've attached sample application with ContextMenu attached to the header only and with menu allowing to change columns visibility. There are no missing bindings.

    If that is not your case could you send us sample project demonstrating the problem?


    Best wishes,
    Hristo
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Back to Top
DevCraft banner