質問の種類ごとに列を持つフォームにデータグリッドがあります。後続の列の質問タイプごとに、必須の質問の数とオプションの質問の数を受け入れたいので、その列を2つに分割したいと思います。
stackoverflow.com のおかげで、winforms でこれを達成しました。
私はWPFで同じことを達成しようとしています
前もって感謝します
質問の種類ごとに列を持つフォームにデータグリッドがあります。後続の列の質問タイプごとに、必須の質問の数とオプションの質問の数を受け入れたいので、その列を2つに分割したいと思います。
stackoverflow.com のおかげで、winforms でこれを達成しました。
私はWPFで同じことを達成しようとしています
前もって感謝します
これは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>
したがって、基本的には同じデフォルトのヘッダー レイアウトを使用しますが、2 つのヘッダーが結合されているように見えるDataGrid
ようにハックします。
C#
DataGrid
あなたの例に名前を付けますx:Name="MyDataGrid"
。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>
列を追加するときに 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);
<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>
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>
このリンクで説明されている GridHelper クラスに AutoColumns プロパティを追加しました
#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