WPF datagrid column heading span more than once column

后端 未结 6 602
轮回少年
轮回少年 2020-12-30 17:14

In a WPF datagrid is it possible to group column headings?

What I\'m after is

| Column 1 | Column 2 | Column 3|
| a  b  c  | a  b  c  | a  b  c |
|          


        
6条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-30 17:24

    This is an old post and I liked D'Hags answere. Unfortunatley it didn't satisfy my reqiurement entirely. Hence I extended D'Hags solution a bit which allows now:

    • column spans are possible in an arbitrary manner and not only the entire row
    • column span is defined by using object references. When column 2 and column 3 are databinding to the same object reference then a span is rendered
    • the column span should behave exaclty like the others columns, so that for instance selections are possible.

    The solution goes like this:

    A Datagrid with the a style:

        
            
                
            
    
        
    

    That sets the following class to be used instead of using DataGridCellsPanel directly:

    public class DataGridSpannedCellPanel : DataGridCellsPanel
    {
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            if (DataContext is IEnumerable)
            {
                base.ArrangeOverride(arrangeSize);
    
                IEnumerable data = ((IEnumerable)DataContext).Cast();
                double totalPreviousWidth = 0;
                double totalPos = 0;
    
    
                List columnSize = new List();
                double currentSize = 0;
    
    
                for (int i = 0; i < data.Count(); ++i)
                {
                    Object el = data.ElementAt(i);
                    Object nextEl = null;
    
                    UIElement uiel = InternalChildren[i];
    
                    if (data.Count() > i + 1)
                    {
                        nextEl = data.ElementAt(i + 1);
                    }
    
    
                    if (Object.ReferenceEquals(el, nextEl) && el != null)
                    {
                        totalPreviousWidth += uiel.RenderSize.Width;
                        uiel.Arrange(new Rect(new Point(0, 0), new Size(0, 0)));
                    }
                    else
                    {
                        if (totalPreviousWidth > 0)
                        {
                            uiel.Arrange(new Rect(new Point(totalPos, 0),
                        new Size(totalPreviousWidth + uiel.RenderSize.Width, uiel.RenderSize.Height))
    
                         );
                            currentSize = totalPreviousWidth + uiel.RenderSize.Width;
                        }
    
                        totalPos += uiel.RenderSize.Width;
    
                        totalPreviousWidth = 0;
                    }
                }
    
                return arrangeSize;
            }
            else
            {
                return base.ArrangeOverride(arrangeSize);
            }
    
        }
     }
    }
    
    
    

    And it used in the following way:

    public partial class MainWindow : Window
    {
    
        void AddColumn(DataGrid dg, int i)
        {
    
            var col = new DataGridTextColumn();
            col.Header = (char)('A' + i);
            col.Binding = new Binding("[" + i + "]");
    
            dg.Columns.Add(col);
    
        }
    
        public MainWindow()
        {
            InitializeComponent();
    
            for (int i = 0; i < 10; ++i)
            {
                AddColumn(dataGrid, i);
            }
    
            List rows = new List();
    
            String[] txtHeader = new string[7];
            String multiSpan = "MergedColumn";
            txtHeader[0] = "Col1";
            txtHeader[1] = "Col2";
            txtHeader[2] = "Col3";
            // these columns should be merged to one, which is indicated by assigning 
            // the same reference to all columns.
            txtHeader[3] = multiSpan;
            txtHeader[4] = multiSpan;
            txtHeader[5] = multiSpan;
    
            int[] intArr = new int[10];
            for (int i = 0; i < 10; i++)
            {
                intArr[i] = i;
            }
    
            rows.Add(txtHeader);
            rows.Add(intArr);
    
            dataGrid.ItemsSource = rows;
        }
    }
    }
    
        

    提交回复
    热议问题