Search code examples
c#wpfwpfdatagriddatagridcolumndatagridcolumnheader

WPF - DataGridColumn Width not Returning Expected Value


.NET4.0 : I'm building a DataGrid in a codebehind, so I'm not using any XAML. C# only. When the user right clicks anywhere in the column header, I want to show a context menu. Here's some code to give you an idea:

    public void MakeAllColumns()
    {
        for (int i = 0; i < AllColumnDisplayNames.Length; i++)
        {
            // create a new column depending on the data to be displayed
            DataGridTextColumn col = new DataGridTextColumn();
            col.MaxWidth = 300;

            // create a new Textblock for column's header and add it to the column
            TextBlock headerText = new TextBlock() { Text = AllColumnDisplayNames[i] };
            col.Header = headerText;

            /// create a new context menu and add it to the header
            ContextMenu menu = new ContextMenu();
            headerText.ContextMenu = menu;

            // build the context menu depending on the property
            menu.Items.Add(new Button() { Content = "FOOBAR" });

            // add the bindings to the data
            col.Binding = new Binding(AllColumnBindings[i]);

            AllColumns.Add(AllColumnDisplayNames[i], col);
        }
    }

The problem with this approach is that the user needs to click on the actual TextBox in order to activate the context menu, as opposed to anywhere on the header.

As I can't think of a way to make the TextBox fill the header width, all I can think to do is change the TextBox width property to bind to the column's width. The columns stretch to fit their content, and as such they have different widths. However, when I print all the columns ActualWidth properties to console, it says that they all have width 20, which is not what my GUI looks like. How can I get the column width that corresponds to how it looks in my GUI?


Solution

  • To you solve your problem must exchange o your body method by this body:

    This code was tested:

    for (int i = 0; i < AllColumnDisplayNames.Length; i++)
                    {
                        // create a new column depending on the data to be displayed
                        DataGridTextColumn col = new DataGridTextColumn();
                        col.MaxWidth = 300;
    
                        /// create a new context menu 
                        ContextMenu menu = new ContextMenu();
    
                        // build the context menu depending on the property
                        menu.Items.Add(new Button() { Content = "FOOBAR" });
    
                        // create a new column's header and add it to the column
                        DataGridColumnHeader head = new DataGridColumnHeader() { Content = AllColumnBindings[i] };
                        head.ContextMenu = menu;//add context menu to DataGridColumnHeader
                        col.Header = head;
    
                        // add the bindings to the data
                        col.Binding = new Binding(AllColumnBindings[i]);
    
                        AllColumns.Add(AllColumnDisplayNames[i], col);
                    }
    

    Instead of using TextBlock I used DataGridColumnHeader, which has the ContextMenu property, thus occupying all the space (height and width) of the Header.