在我的窗户上,我有一个
GroupBox
。我想在其中构建一个水平对齐的表格 GroupBox
。水平对齐是指标签和输入位于同一网格行或 x 轴上的表单。单独的表单标签+输入位于各自的行中。
由于
GroupBox
只能有一个子内容,我认为我需要使用 Grid
或 StackPanel
。我正在尝试使用 StackPanel
,因为这看起来更简单,并且应该实现我的目标。
我试图解决的问题是如何将输入和标签分组为一个单元,以便它们可以水平彼此相邻,但在
StackPanel
内垂直堆叠为一对。
最好使用
Grid
,这样你就可以让标签和输入垂直排列。虽然使用堆栈面板并非不可能,但要困难得多。如果将网格的 RowDefinition
高度设置为“自动”,网格将仅达到所需的高度:
<GroupBox>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Label1"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Input1}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Label2"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Input2}"/>
etc.
</Grid>
</GroupBox>
您可能需要使用边距和/或填充和水平对齐来使布局完全符合您的要求,但这应该为您提供实现您想要的效果所需的控制。
您可以在组框内使用方向等于垂直的堆栈面板,并在该堆栈面板内使用另一个方向等于水平的堆栈面板,用于标签和输入,就像下面的示例代码一样。
<GroupBox Header="Sample GroupBox">
<StackPanel Orientation="Vertical">
<StackPanel Name="input1" Orientation="Horizontal">
<Label Content="input1"/>
<TextBox/>
</StackPanel>
<StackPanel Name="input2" Orientation="Horizontal">
<Label Content="input2"/>
<TextBox/>
</StackPanel>
<StackPanel Name="input3" Orientation="Horizontal">
<Label Content="input3"/>
<TextBox/>
</StackPanel>
</StackPanel>
</GroupBox>
您可能会发现有用的一个功能是网格共享大小范围。它可以帮助您通过共享列来对齐多个不同网格中的元素 ow 尺寸,像这样:
<GroupBox Header="Sample GroupBox">
<StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="firstGroup" />
<ColumnDefinition Width="Auto" SharedSizeGroup="secondGroup" />
</Grid.ColumnDefinitions>
<Label Content="input11" Grid.Column="0" />
<TextBox Grid.Column="1" Width="100"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="firstGroup" />
<ColumnDefinition Width="Auto" SharedSizeGroup="secondGroup" />
</Grid.ColumnDefinitions>
<Label Content="input2222222" Grid.Column="0" />
<TextBox Grid.Column="1"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="firstGroup" />
<ColumnDefinition Width="Auto" SharedSizeGroup="secondGroup" />
</Grid.ColumnDefinitions>
<Label Content="input3333333333333" Grid.Column="0" />
<TextBox Grid.Column="1"/>
</Grid>
</StackPanel>
</GroupBox>
我并不是说上面的代码中有必要,但这只是示例。通常,您希望在 ItemsControl 的 ItemTemplate 等中使用网格,并且希望所有项目对齐。这里共享大小范围可能会有所帮助。
这里是一个轻量级的表单布局解决方案,不需要第三方库和很多布局属性代码:
(仅限核心代码:)
C# 代码:
using System.Windows;
using System.Windows.Controls;
namespace Flithor_Codes
{
public class TemplatedItemsControl : ItemsControl
{
// force apply ItemTemplate for each control element
protected override bool IsItemItsOwnContainerOverride(object item)
{
return false;
}
// apply ItemTemplate for each generated container
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
((ContentPresenter)element).ContentTemplate = ItemTemplate;
}
}
// For define the field name
public static class SimpleField
{
public static readonly DependencyProperty FieldNameProperty = DependencyProperty.RegisterAttached(
"FieldName", typeof(string), typeof(SimpleField), new PropertyMetadata(default(string)));
public static void SetFieldName(DependencyObject element, string value)
{
element.SetValue(FieldNameProperty, value);
}
public static string GetFieldName(DependencyObject element)
{
return (string)element.GetValue(FieldNameProperty);
}
}
}
在 XAML 中使用:
<!-- Set this control is Shared Size Scope make ColumnDefinition.SharedSizeGroup works -->
<fc:TemplatedItemsControl Grid.IsSharedSizeScope="True">
<fc:TemplatedItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type FrameworkElement}">
<Grid Margin="0,0,0,3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
MinWidth="80"
SharedSizeGroup="FieldName" />
<ColumnDefinition Width="8" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Right"
VerticalAlignment="Center"
Text="{Binding Path=(fc:SimpleField.FieldName)}" />
<ContentPresenter Grid.Column="2" Content="{Binding}" />
</Grid>
</DataTemplate>
</fc:TemplatedItemsControl.ItemTemplate>
<!-- simple fields editor definition -->
<TextBox x:Name="txt_Name"
fc:SimpleField.FieldName="Name"
Text="{Binding Name}" />
<ComboBox x:Name="txt_Sex"
fc:SimpleField.FieldName="Sex"
ItemsSource="{x:Static my:Constains.SexList}"
SelectedItem="{Binding Sex}" />
<TextBox x:Name="txt_Age"
fc:SimpleField.FieldName="Age"
Text="{Binding Age}" />
<ComboBox x:Name="txt_Job"
fc:SimpleField.FieldName="Job"
IsEditable="True"
ItemsSource="{x:Static my:Constains.JobList}"
Text="{Binding Job}" />
</fc:TemplatedItemsControl>