3

在此处输入图像描述我的表单中有一个数据网格,其中包含每个问题类型的列。我希望将该列分成两列,因为我想接受后续列中每种问题类型的必填问题和可选问题的数量。

感谢stackoverflow.com,我在winforms中实现了这一点。

我正在尝试在 WPF 中实现相同的目标

提前致谢

4

3 回答 3

1

我想这是DataGrid你想要的布局......对吧?

.------.-----------------.--------.
|      |   ID Details    |        |
| Name |-----------------| Status |
|      | ID   | Passport |        |
|------|------|----------|--------|
|X     | 123  | E567868  | Present|
|Y     | 236  | 7875678  | Absent |
'------'------'----------'--------'

WPF 数据网格并不容易支持这一点。但是你可以做一些有弹性的编码。下面的代码可以拆分标题。你需要小心...

当拆分列重新排序(DataGrid.ColumnReordered 事件)时,其公共父标题下的所有兄弟列应一起移动。我把那个代码留给你。

有一些自定义样式DataGridHeaders

<Style TargetType="{x:Type Primitives:DataGridColumnHeader}" 
  x:Key="SplitHeaderStyle">
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="{x:Type Primitives:DataGridColumnHeader}">
        <DockPanel LastChildFill="True">
        <Grid DockPanel.Dock="Bottom">
            <Controls:DataGridHeaderBorder 
            SortDirection="{TemplateBinding SortDirection}"
            IsHovered="{TemplateBinding IsMouseOver}"
            IsPressed="{TemplateBinding IsPressed}"
            IsClickable="{TemplateBinding CanUserSort}"
            Background="{TemplateBinding Background}"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Padding ="{TemplateBinding Padding}"
            SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
            SeparatorBrush="{TemplateBinding SeparatorBrush}">
            <ContentPresenter 
            Content="{Binding RelativeSource={RelativeSource TemplatedParent},
                      Path=Content[0]}"
            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
            HorizontalAlignment="Center"/>
            </Controls:DataGridHeaderBorder>
            <Thumb x:Name="PART_LeftHeaderGripper"
               HorizontalAlignment="Left"
               Style="{StaticResource ColumnHeaderGripperStyle}"/>
            <Thumb x:Name="PART_RightHeaderGripper"
               HorizontalAlignment="Right"
               Style="{StaticResource ColumnHeaderGripperStyle}"/>
        </Grid>
        <Grid DockPanel.Dock="Top">
            <Controls:DataGridHeaderBorder
            HorizontalAlignment="Stretch"
            IsClickable="False"
            Background="{TemplateBinding Background}"
            BorderBrush="{TemplateBinding SeparatorBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Padding ="{TemplateBinding Padding}"
            SeparatorVisibility="{TemplateBinding Tag}"
            SeparatorBrush="{TemplateBinding SeparatorBrush}">
            <ContentPresenter 
                Content="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                          Path=Content[1]}"
                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                Margin="-8,2,-10,2"/>
            </Controls:DataGridHeaderBorder>
            <Thumb x:Name="PART_LeftSplitHeaderGripper"
            HorizontalAlignment="Right"
            Visibility="{TemplateBinding Tag}"
            Style="{StaticResource ColumnHeaderGripperStyle}"/>
        </Grid>
        </DockPanel>
    </ControlTemplate>
    </Setter.Value>
</Setter>
</Style>

<Style TargetType="{x:Type Primitives:DataGridColumnHeader}" 
   BasedOn="{StaticResource SplitHeaderStyle}"
   x:Key="SplitHeaderLeftStyle">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Tag" Value="{x:Static Visibility.Visible}"/>
</Style>

<Style TargetType="{x:Type Primitives:DataGridColumnHeader}" 
   BasedOn="{StaticResource SplitHeaderStyle}"
   x:Key="SplitHeaderRightStyle">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
<Setter Property="Tag" Value="{x:Static Visibility.Collapsed}"/>
</Style>

有这样排列的列...

<Controls:DataGrid.Columns>
<Controls:DataGridTextColumn 
         Header="Name" 
         Binding="{Binding Name}"/>
<Controls:DataGridTextColumn 
         Binding="{Binding ID}" 
    HeaderStyle="{StaticResource SplitHeaderRightStyle}">
    <Controls:DataGridTextColumn.Header>
    <x:ArrayExtension Type="System:String">
        <System:String>ID</System:String>
        <System:String>ID De</System:String>                            
    </x:ArrayExtension>
    </Controls:DataGridTextColumn.Header>
</Controls:DataGridTextColumn>
<Controls:DataGridTextColumn 
         Binding="{Binding Passport}"
    HeaderStyle="{StaticResource SplitHeaderLeftStyle}">
    <Controls:DataGridTextColumn.Header>
    <x:ArrayExtension Type="System:String">
        <System:String>Passport</System:String>
        <System:String>tails</System:String>                            
    </x:ArrayExtension>
    </Controls:DataGridTextColumn.Header>
</Controls:DataGridTextColumn>
<Controls:DataGridTextColumn 
            Header="Status"
            Binding="{Binding Status}"/>
  </Controls:DataGrid.Columns>

所以基本上你使用相同的默认标题布局,但以两个标题看起来像是连接在一起DataGrid的方式破解它。

C#

  1. 命名你的DataGrid例如x:Name="MyDataGrid"
  2. 将 XAML 中的所有样式保存在<DataGrid.Resources ..>标记中。确保他们已经x:Key设置。例如x:Key="SplitHeaderLeftStyle"&x:Key="SplitHeaderRightStyle"

    <DataGrid x:Name="MyDataGrid">
         <DataGrid.Resources>
             <Style 
                  TargetType="{x:Type Primitives:DataGridColumnHeader}" 
                  x:Key="SplitHeaderStyle" .../>
    
             <Style x:Key="SplitHeaderLeftStyle" 
                    BasedOn="{StaticResource SplitHeaderStyle}".../>
    
             <Style x:Key="SplitHeaderRightStyle"
                    BasedOn="{StaticResource SplitHeaderStyle}" .../>
         </DataGrid.Resources>
         ...
    </DataGrid> 
    
  3. 在 C# 代码中添加列时,通过它们的Key.

      var dgIDColumn 
        = new DataGridTextColumn()
          {
            Header = new string[] { "ID", "ID Det" },
            Binding = new Binding() { Path = new PropertyPath("ID") },
            HeaderStyle = MyDataGrid.FindResource("SplitHeaderRightStyle") as Style;
          };
    
     MyDataGrid.Columns.Add(dgIDColumn);
    
      var dgPassportColumn 
       = new DataGridTextColumn()
         {
            Header = new string[] { "Passport", "ails" },
            Binding = new Binding() { Path = new PropertyPath("Passport") },
            HeaderStyle = MyDataGrid.FindResource("SplitHeaderLeftStyle") as Style;
         };
    
      MyDataGrid.Columns.Add(dgPassportColumn);
    
于 2012-10-23T11:40:57.187 回答
0
<DataGrid ItemsSource="{Binding PeopleList}" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Name">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate DataType="{x:Type local:Person}">
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        <DataGridTemplateColumn>
            <DataGridTemplateColumn.HeaderTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="10"/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <TextBlock Text="Question1" Grid.ColumnSpan="2"/>
                        <TextBlock Text="Compulsory" Grid.Row="1"/>
                        <TextBlock Text="Optional Q" Grid.Row="1" Grid.Column="2"/>
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.HeaderTemplate>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate DataType="{x:Type local:Person}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="65"/>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Question.Col1}"/>
                        <TextBlock Text="{Binding Question.Col2}" Grid.Column="2"/>
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>
于 2012-10-19T12:37:04.863 回答
0

您可以根据自己的喜好修改 ItemsControl.ItemContainerStyle 的 DataTriggers 中的 Row/Column/ColumnSpan/RowSpan。

<ItemsControl ItemsSource="{Binding Path=Cells}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid 
                local:GridHelpers.ColumnCount="{Binding NumOfColumns}"
                local:GridHelpers.AutoColumns="0,1"
                local:GridHelpers.RowCount="{Binding NumOfRows}"
                local:GridHelpers.AutoRows="0,1">
            </Grid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Grid.Row" Value="{Binding Path=RowIndex}"/>
            <Setter Property="Grid.Column" Value="{Binding Path=ColumnIndex}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=CellType}" Value="BaseCell">
                    <Setter Property="ContentTemplate" Value="{StaticResource BaseCell}"/>
                    <Setter Property="Grid.ColumnSpan" Value="{Binding Path=ColumnSpan}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=CellType}" Value="CornerHeader">
                    <Setter Property="ContentTemplate" Value="{StaticResource CornerHeader}"/>
                    <Setter Property="Grid.RowSpan" Value="2"/>
                    <Setter Property="Grid.ColumnSpan" Value="2"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=CellType}" Value="PersonNameCell">
                    <Setter Property="ContentTemplate" Value="{StaticResource PersonNameCell}"/>
                </DataTrigger>
                ...
            </Style.Triggers>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

我已将 AutoColumns 属性添加到 GridHelper 类中,此链接中对此进行了说明

    #region AutoColumns Property

    /// <summary>
    /// Makes the specified Column's Width equal to Auto. 
    /// Can set on multiple Columns
    /// </summary>
    public static readonly DependencyProperty AutoColumnsProperty =
        DependencyProperty.RegisterAttached(
            "AutoColumns", typeof(string), typeof(GridHelpers),
            new PropertyMetadata(string.Empty, AutoColumnsChanged));

    // Get
    public static string GetAutoColumns(DependencyObject obj)
    {
        return (string)obj.GetValue(AutoColumnsProperty);
    }

    // Set
    public static void SetAutoColumns(DependencyObject obj, string value)
    {
        obj.SetValue(AutoColumnsProperty, value);
    }

    // Change Event - Makes specified Column's Width equal to Auto
    public static void AutoColumnsChanged(
        DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        if (!(obj is Grid) || string.IsNullOrEmpty(e.NewValue.ToString()))
            return;

        SetAutoColumns((Grid)obj);
    }

    private static void SetAutoColumns(Grid grid)
    {
        string[] autoColumns = GetAutoColumns(grid).Split(',');

        for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
        {
            if (autoColumns.Contains(i.ToString()))
                grid.ColumnDefinitions[i].Width = GridLength.Auto;
        }
    }

    private static void SetAutoRows(Grid grid)
    {
        string[] autoRows = GetAutoRows(grid).Split(',');

        for (int i = 0; i < grid.RowDefinitions.Count; i++)
        {
            if (autoRows.Contains(i.ToString()))
                grid.RowDefinitions[i].Height = GridLength.Auto;
        }
    }
    #endregion
于 2012-10-22T19:46:16.007 回答