我有一个WPF表单,我想在其上列出一个标准表单。每个表单元素都有一个标签,然后是一个控件。非常标准的东西。
如果我使用包装面板,它可能导致标签和控件分离,但我希望它们保持在一起。是否有一些WPF等效于<nobr/>
?
网格工作,并允许列跨越等,但我真的很讨厌你在每个控件上指定列和行。这使得将内容重新排序或插入列表非常不方便。
有没有办法让网格使用更多HTML样式的列/行,其中项目是他们所在行的子项,以便我可以轻松地重新排序?
是否有其他控件可以让我轻松布局表单?
答案 0 :(得分:20)
是否有一些WPF相当于nobr?
请记住,您可以嵌套面板:
<WrapPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<Label>Some field</Label>
<TextBox>Some value</TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label>Another field</Label>
<TextBox>Another value</TextBox>
</StackPanel>
...
</WrapPanel>
此外,对于柱状布局,Grid的共享大小范围可以协调使用它的任意数量的网格:
<StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0">Some field</Label>
<TextBox Grid.Column="1">Some value</TextBox>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0">Another field</Label>
<TextBox Grid.Column="1">Another value</TextBox>
</Grid>
</StackPanel>
我有点讨厌XAML的冗长,特别是你必须重复列定义。虽然如果你正确地构建你的类并使用模板,它并不是那么糟糕。请注意,您不会在此方案中的任何位置跟踪行号,因此重新排序字段很简单。
答案 1 :(得分:6)
您可能正在寻找的是堆栈面板。使用垂直StackPanel可以一致地排列标签和控件。对于每个标签和控件,您可能需要一个像这样的水平堆栈面板
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Label Width="150">Name</Label>
<TextBox Width="200" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Width="150">Date of Birth</Label>
<DatePicker Width="200" />
</StackPanel>
</StackPanel>
现在,您可以添加,删除,编辑和重新排序内容,而无需担心列和行。
答案 2 :(得分:5)
尝试使用UniformGrid控件。
答案 3 :(得分:2)
如果您能够给予它,我推荐Expression Blend,如果您要进行大量的UI设计。它允许更简单地查看项目。将控件嵌套到各种容器中是使UI动态化但结构化的好方法。
通常我会使用Grid面板将窗口分成功能区域。然后我将使用一系列StackPanels(通常是一个垂直的堆栈面板,里面有水平StackPanels,每个都有一个标签和文本框)。
不幸的是,网格只能像你说的那样工作。其中的元素指定它们所在的行和/或列。如果使用Blend,添加网格列或行将使控件自动神奇地更改行/列规范以保持其放置位置。
希望它有所帮助。
Microsoft的更新:
VS2012将很多Expression Blend功能融入WPF设计器中。由于开发人员可以访问Blend的许多很酷的工具,因此很多需要Blend的副本。
答案 4 :(得分:2)
查看卡尔的内容。
简单干净的xaml:
<pt:Form x:Name="formMain" Style="{DynamicResource standardForm}" Grid.Row="1">
<TextBox pt:FormItem.LabelContent="_First Name" />
<TextBox pt:FormItem.LabelContent="_Last Name" />
<TextBox pt:FormItem.LabelContent="_Phone" Width="150" HorizontalAlignment="Left" />
<CheckBox pt:FormItem.LabelContent="Is _Active" />
</pt:Form>
答案 5 :(得分:2)
示例xaml:
Button*
这是一个markupextension,为一个漂亮的浅视觉树返回一个vanilla WPF <UserControl ...
xmlns:autoRowGrid="http://gu.se/AutoRowGrid"
...>
<autoRowGrid:Grid ColumnDefinitions="Auto *">
<autoRowGrid:Row Name="first row">
<TextBlock Text="foo1" />
<TextBox Text="{Binding Value1}" />
</autoRowGrid:Row>
<autoRowGrid:Row Name="second row">
<TextBlock Text="foo2" />
<TextBox Text="{Binding Value2}" />
</autoRowGrid:Row>
</autoRowGrid:Grid>
...
。
答案 6 :(得分:0)
在我们的产品中,我们使用HeaderedContentControl在网格中布置表单。控件模板具有标签和填充/边距,以便控件的内容始终适当间隔。在XAML中,我们只需将它们添加到列中。
我发布了一些XAML,但我正在设置一台新计算机。 :|但是从我记忆中它看起来像这样:
<Style x:Key="hccFormStyle" Targettype="{x:Type HeaderedContentControl}>
... some setters for colors, margin, padding, etc...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Label Content={Binding Content} Target={Binding Tag}> <-- pass the control for the access key with the tag
<ContentPresenter>
</ControlTemplate>
...triggers if necessary - hover states, etc...
</style>
然后在网格中,您定义行和列,并将其中一个放在每个单元格中,或者只放在每行中:
<HeaderedContentControl x:Name="username" Grid.Column=0 Content="User Name" Tag=textboxUserName>
<Textbox x:Name=textboxUserName>
</HeaderedContentControl>
我可能会回答一个不同的问题,但这就是我们如何布置表格。
答案 7 :(得分:0)
我遇到了同样的问题,在基于网格的布局中重新排序控件真是太痛苦了。
所以我写了一个自定义面板,它做了“表单布局”(两列的组,所有标签大小相同,所有控件大小相同,所有内容都对齐等),它位于我的博客上:{{3} }
答案 8 :(得分:0)
我今天遇到这个帖子时遇到了同样的问题,使用这个帖子中的答案,我想出了一个简单的文本/文本对的可管理的解决方案。要添加新字段,只需展开“FormItems”集合。
的xmlns:C = “CLR-名称空间:System.Collections中;装配= mscorlib程序”
<Window.Resources>
<c:ArrayList x:Key="FormItems">
<c:DictionaryEntry Key="First Name" Value="John"/>
<c:DictionaryEntry Key="Last Name" Value="Smith"/>
</c:ArrayList>
</Window.Resources>
<ItemsControl ItemsSource="{StaticResource FormItems}" Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock>
<Run Text="{Binding Key}"/><Run Text=": "/>
</TextBlock>
<TextBox Grid.Column="1" Text="{Binding Value}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
没有考虑边距和填充,它只是显示了使用DataTemplate重用每个项目的布局的概念。它可以很容易地适应包括其他数据类型和控件。您甚至可以使用ItemTemplateSelector根据DictionaryEntry.Value的类型选择不同的模板
修改强>
我发现使DataBinding更容易的另一种方法是使用Visual Studio创建一个新的WPF“自定义控件”。这样做会创建一个名为Themes / Generic.xaml的新文件,并在其中定义新的默认布局。一些简单的编辑,我们可以使用ItemsControl来显示我们的新控件。
新课程:
public class FormControlItem : ContentControl
{
public object Field {
get { return base.GetValue(FieldProperty); }
set { base.SetValue(FieldProperty, value); }
}
static FormControlItem() {
DefaultStyleKeyProperty.OverrideMetadata(
typeof(FormControlItem),
new FrameworkPropertyMetadata(typeof(FormControlItem)));
}
public static readonly DependencyProperty FieldProperty =
DependencyProperty.Register(
"Field",
typeof(object),
typeof(FormControlItem),
new FrameworkPropertyMetadata());
}
<强>主题/ Generic.xaml:强>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApplication">
<Style TargetType="{x:Type local:FormControlItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:FormControlItem}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentPresenter ContentSource="Field"/>
<ContentPresenter Grid.Column="1" ContentSource="Content"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
用法示例:
<ItemsControl Grid.IsSharedSizeScope="True">
<local:FormControlItem Field="Name: ">
<TextBox Text="{Binding Path=Name}"/>
</local:FormControlItem>
<local:FormControlItem Field="Type: ">
<ComboBox
SelectedItem="{Binding Path=Type}"
ItemsSource="{Binding Path=TypeValues}"/>
</local:FormControlItem>
<local:FormControlItem Field="Category: ">
<TextBox Text="{Binding Path=Category}"/>
</local:FormControlItem>
</ItemsControl>