WPF datagrid列标题跨越多个列

WPF datagrid列标题跨越多个列,wpf,datagrid,Wpf,Datagrid,在WPF数据网格中,是否可以对列标题进行分组 我要的是 | Column 1 | Column 2 | Column 3| | a b c | a b c | a b c | | z x y | z x y | z x y | 我四处搜索,找不到明显的方法。我可以使用一个模板列,然后在每个模板中模拟额外的单元格,但这对于排序等来说不太好 我想我想说的是人们是如何跨越多个colun的列标题的 如果您有任何帮助或想法,我们将不胜感激。为您的专栏定制标题模板

在WPF数据网格中,是否可以对列标题进行分组

我要的是

| Column 1 | Column 2 | Column 3|
| a  b  c  | a  b  c  | a  b  c |
| z  x  y  | z  x  y  | z  x  y |
我四处搜索,找不到明显的方法。我可以使用一个模板列,然后在每个模板中模拟额外的单元格,但这对于排序等来说不太好

我想我想说的是人们是如何跨越多个colun的列标题的


如果您有任何帮助或想法,我们将不胜感激。

为您的专栏定制标题模板

    <DataGrid>
        <DataGrid.Columns>
            <DataGridTextColumn>
                <DataGridTextColumn.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock>Column 1</TextBlock>
                            <TextBlock>xyz</TextBlock>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTextColumn.HeaderTemplate>
            </DataGridTextColumn>
            <DataGridTextColumn Header="Header" />
        </DataGrid.Columns>
    </DataGrid>

第1栏
xyz

您最好删除列标题并在网格外添加自己的列标题。有一篇很好的帖子展示了如何制作跨越多列的“标题”。

这个问题有点老了,但它是我在寻找解决方案时第一个出现的谷歌结果之一,我不喜欢这里发布的任何一个答案。因此,这里有一个简单的替代方法,使用自定义头和cliptobunds=False

<DataGridTextColumn.Header>
    <StackPanel Orientation="Horizontal">
        <TextBlock x:Name="HeightSpacer" Text="P" FontWeight="Bold" />
        <Canvas Height="{Binding ElementName=HeightSpacer, Path=ActualHeight}">
            <TextBlock Text="hone Numbers" FontWeight="Bold" ClipToBounds="False" />
        </Canvas>
    </StackPanel>
</DataGridTextColumn.Header>

您需要做的唯一一件事是确保此标题正在垃圾邮件中的任何列的组合宽度至少为标题列的宽度


包含标题文本的第一个字符的
TextBlock
Canvas.Height
绑定用于阻止标题所需的高度。只有当您的完整datagrid标题没有定义标题高度的元素,或者滥发多个列的标题比其他列大(这是我的情况……这是唯一一个带有粗体文本的标题列)时,才需要它。

这是一个旧线程,但我想我应该分享一下我是如何做到的

在我的应用程序中,我希望在一个列标题“维护费用日期”下显示三列日期条目。我创建了一个列,包含两个数据模板,一个用于显示,一个用于编辑:

<DataGrid.Resources>
  <DataTemplate x:Key="cellTemplate">
     <Grid>
        <Grid.ColumnDefinitions>
           <ColumnDefinition Width="100" />
           <ColumnDefinition Width="100" />
           <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        <TextBlock x:Name="tbDate1"
                    Text="{Binding Path=Date1}"
                    Grid.Column="0" />
        <TextBlock x:Name="tbDate2"
                    Text="{Binding Path=Date2}"
                    Grid.Column="1" />
        <TextBlock x:Name="tbDate3"
                    Text="{Binding Path=Date3}"
                    Grid.Column="2" />
     </Grid>
  </DataTemplate>
  <DataTemplate x:Key="cellEditingTemplate">
     <Grid>
        <Grid.ColumnDefinitions>
           <ColumnDefinition Width="100" />
           <ColumnDefinition Width="100" />
           <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        <DatePicker Grid.Column="0"
                    Margin="0"
                    Name="dpDate1"
                    Width="100"
                    SelectedDate="{Binding Path=Date1}" />
        <DatePicker Grid.Column="1"
                    Margin="0"
                    Name="dpDate2"
                    Width="100"
                    SelectedDate="{Binding Path=Date2}" />
        <DatePicker Grid.Column="2"
                    Margin="0"
                    Name="dpDate3"
                    Width="100"
                    SelectedDate="{Binding Path=Date3}" />
     </Grid>
  </DataTemplate>

然后我将该列定义为DataGridTemplateColumn,指向上面的DataTemplates:

<DataGrid.Columns>
....
   <DataGridTemplateColumn CellTemplate="{StaticResource cellTemplate}"
                           Header="Maintenance Fee Dates"
                           CellEditingTemplate="{StaticResource cellEditingTemplate}" />
....
</DataGrid.Columns>

....
....
因为DataTemplate是用一个有三个固定长度列的网格布局的,所以我在单列标题下得到了三个不错的日期列(编辑时是日期选择器)

水平网格线可以由网格处理。要在三列之间设置垂直网格线,只需将中间列的控件放在边框控件中。将边框控件设置为与网格列相同的宽度,仅显示其右边框和左边框,并将其边框笔刷设置为与DataGrid网格线的颜色相匹配:

  <DataTemplate x:Key="cellTemplate">
     <Grid>
        <Grid.ColumnDefinitions>
           <ColumnDefinition Width="100" />
           <ColumnDefinition Width="100" />
           <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        <TextBlock x:Name="tbDate1"
                    Text="{Binding Path=Date1}"
                    Grid.Column="0" />
        <Border BorderThickness="1,0,1,0"
                BorderBrush="DarkGray"
                Width="100">
           <Border.Child>
              <TextBlock x:Name="tbDate2"
                          Text="{Binding Path=Date2}"
                          Grid.Column="1" />
           </Border.Child>
        </Border>
        <TextBlock x:Name="tbDate3"
                    Text="{Binding Path=Date3}"
                    Grid.Column="2" />
     </Grid>
  </DataTemplate>

这是一篇老文章,我喜欢D'Hags Ansare。不幸的是,它不能完全满足我的要求。因此,我对D'Hags解决方案进行了一些扩展,现在允许:

  • 列跨距可以是任意的,而不仅仅是整行
  • 列跨度是通过使用对象引用定义的。当列2和列3数据绑定到同一对象引用时,将呈现一个范围
  • 列跨度的行为应与其他列相似,以便可以进行实例选择
解决方案如下:

具有以下样式的数据网格:

    <DataGrid  x:Name="dataGrid" ItemsSource="{Binding}" AutoGenerateColumns="False">
        <DataGrid.Resources>
            <Style TargetType="DataGridRow">

                        <Setter Property="ItemsPanel" >
                            <Setter.Value>
                                <ItemsPanelTemplate>
                                    <local:DataGridSpannedCellPanel ></local:DataGridSpannedCellPanel>

                                </ItemsPanelTemplate>
                            </Setter.Value>
                        </Setter>

            </Style>
        </DataGrid.Resources>

    </DataGrid>

设置要使用的以下类,而不是直接使用DataGridCellsPanel:

public class DataGridSpannedCellPanel : DataGridCellsPanel
{
    protected override Size ArrangeOverride(Size arrangeSize)
    {
        if (DataContext is IEnumerable)
        {
            base.ArrangeOverride(arrangeSize);

            IEnumerable<Object> data = ((IEnumerable)DataContext).Cast<Object>();
            double totalPreviousWidth = 0;
            double totalPos = 0;


            List<int> columnSize = new List<int>();
            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);
        }

    }
 }
}
公共类DataGridSpandCellPanel:DataGridCellsPanel
{
受保护的替代尺寸ArrangeOverride(尺寸arrangeSize)
{
if(DataContext是IEnumerable)
{
base.ArrangeOverride(arrangeSize);
IEnumerable数据=((IEnumerable)DataContext).Cast();
双重总宽度=0;
双倍totalPos=0;
List columnSize=新列表();
双电流大小=0;
对于(int i=0;ii+1)
{
nextEl=data.ElementAt(i+1);
}
if(Object.ReferenceEquals(el,nextEl)&&el!=null)
{
totalPreviousWidth+=uiel.RenderSize.Width;
排列(新矩形(新点(0,0),新大小(0,0));
}
其他的
{
如果(totalPreviousWidth>0)
{
uiel.排列(新直线(新点)(totalPos,0),
新大小(totalPreviousWidth+uiel.RenderSize.Width、uiel.RenderSize.Height))
);
currentSize=totalPreviousWidth+uiel.RenderSize.Width;
}
totalPos+=uiel.RenderSize.Width;
totalPreviousWidth=0;
}
}
返回安排大小;
}
其他的
{
返回base.ArrangeOverride(arrangeSize);
}
}
}
}

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<object> rows = new List<object>(); 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; } } }

<DataGridTemplateColumn Width=200>
    <DataGridTemplateColumn.CellStyle>
        <Style/> <!-- Disable previously set style -->
    </DataGridTemplateColumn.CellStyle>
    <DataGridTemplateColumn.Header>
        <StackPanel>
            <TextBlock  
                IsEnabled="False"
                Style="{StaticResource TextBlockDataGridHeader}">
                <Run>Windspeeds in area</Run>
            </TextBlock>
            <UniformGrid
                HorizontalAlignment="Stretch"
                Columns="4">
                <Label Grid.Column="0" Content="1"/>
                <Label Grid.Column="1" Content="2"/>
                <Label Grid.Column="2" Content="3"/>
                <Label Grid.Column="3" Content="4"/>
            </UniformGrid>
            <TextBlock           
                Style="{StaticResource TextBlockDataGridHeader}"
                Foreground="Red"
                Text="m/s"/>

        </StackPanel>
    </DataGridTemplateColumn.Header>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <UniformGrid
                HorizontalAlignment="Stretch"
                Columns="4">
                <UniformGrid.Resources>
                    <Style TargetType="TextBox">
                        <Setter Property="Padding" Value="3,0,3,0"/>
                        <!-- Let row background shine through -->
                        <Setter Property="Background" Value="Transparent"/>
                        <Setter Property="Foreground" Value="White"/>
                        <!-- 'Cells' have no border -->
                        <Setter Property="BorderThickness" Value="0"/>
                        <Style.Triggers>
                            <!-- Flip colors on mouseOver -->
                            <Trigger Property="IsMouseOver" Value="True">
                               <Setter Property="Background" Value="White" />
                               <Setter Property="Foreground" Value="Black" />
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </UniformGrid.Resources>                  
                <TextBox 
                    Grid.Column="0"         
                    Text="{Binding VRef0[0],Mode=TwoWay, UpdateSourceTrigger=LostFocus,StringFormat=N1}"/>
                <TextBox 
                    Grid.Column="1"
                    Text="{Binding VRef0[1],Mode=TwoWay, UpdateSourceTrigger=LostFocus,StringFormat=N1}"/>
                <TextBox 
                    Grid.Column="2"
                    Text="{Binding VRef0[2],Mode=TwoWay, UpdateSourceTrigger=LostFocus,StringFormat=N1}"/>
                <TextBox 
                    Grid.Column="3"
                    Text="{Binding VRef0[3],Mode=TwoWay, UpdateSourceTrigger=LostFocus,StringFormat=N1}"/>
            </UniformGrid>
        </DataTemplate>                        
    </DataGridTemplateColumn.CellTemplate> 
</DataGridTemplateColumn>