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

Context Menu in DataGridColumnHeader

4 Answers 211 Views
Menu
This is a migrated thread and some comments may be shown as answers.
Ramesh Subramanian
Top achievements
Rank 1
Ramesh Subramanian asked on 28 Nov 2009, 02:23 PM
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

4 Answers, 1 is accepted

Sort by
0
Hristo
Telerik team
answered on 30 Nov 2009, 03:56 PM
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.
0
Ramesh Subramanian
Top achievements
Rank 1
answered on 01 Dec 2009, 03:42 AM
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); 
                         
                    } 
       
 
 
 
 
            } 
                 
 
 
 
 
        } 
 
         
        
        
 
       
 
         
    } 
 









0
Nikolay
Telerik team
answered on 04 Dec 2009, 09:22 AM
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.
0
Hristo
Telerik team
answered on 08 Dec 2009, 01:08 PM
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.
Tags
Menu
Asked by
Ramesh Subramanian
Top achievements
Rank 1
Answers by
Hristo
Telerik team
Ramesh Subramanian
Top achievements
Rank 1
Nikolay
Telerik team
Share this question
or