好的,第二次尝试。根据您的布局截图,我可以立刻推断出您需要的是WrapPanel
,这是一种布局面板,允许项目填充到达边缘,此时剩余项目会流动到下一行。但您仍想使用ItemsControl
,以便获得数据绑定和动态生成的所有好处。因此,我们将使用ItemsControl.ItemsPanel
属性来指定放置项目的面板。让我们再次从代码后台开始:
public partial class Window1 : Window
{
public ObservableCollection<Field> Fields { get; set; }
public Window1()
{
InitializeComponent();
Fields = new ObservableCollection<Field>();
Fields.Add(new Field() { Name = "Username", Length = 100, Required = true });
Fields.Add(new Field() { Name = "Password", Length = 80, Required = true });
Fields.Add(new Field() { Name = "City", Length = 100, Required = false });
Fields.Add(new Field() { Name = "State", Length = 40, Required = false });
Fields.Add(new Field() { Name = "Zipcode", Length = 60, Required = false });
FieldsListBox.ItemsSource = Fields;
}
}
public class Field
{
public string Name { get; set; }
public int Length { get; set; }
public bool Required { get; set; }
}
这里没有太多变化,但我已编辑示例字段以更好地匹配您的示例。现在让我们看一下魔法发生的地方 - Window
的 XAML:
<Window x:Class="DataBoundFields.Window1"
xmlns="http:
xmlns:x="http:
xmlns:local="clr-namespace:DataBoundFields"
Title="Window1" Height="200" Width="300">
<Window.Resources>
<local:BoolToVisibilityConverter x:Key="BoolToVisConverter"/>
</Window.Resources>
<Grid>
<ListBox x:Name="FieldsListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="" VerticalAlignment="Center"/>
<TextBox Width="" Margin="5,0,0,0"/>
<Label Content="*" Visibility="}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"
Height="}, Path=ActualHeight}"
Width="}, Path=ActualWidth}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
首先,你会注意到ItemTemplate
略有变化。标签仍然绑定到名称属性,但现在文本框宽度绑定到长度属性(这样您就可以拥有不同长度的文本框)。此外,我使用了简单的BoolToVisibilityConverter
(您可以在任何地方找到代码,我不会在此发布)将“*”添加到任何必填字段。
最重要的是,在我们的ListBox
的ItemsPanel
属性中使用了WrapPanel
。这告诉ListBox
生成的任何项都需要被推入水平换行布局(与您的屏幕截图相匹配)。更好的是,面板上的高度和宽度绑定-这意味着,“使此面板与我的父窗口大小相同”。这意味着当我调整Window
大小时,WrapPanel
会相应地调整其大小,从而为项提供更好的布局。