Okay, das zweite Mal ist der Charme. Basierend auf Ihrem Layout-Screenshot kann ich sofort ableiten, dass Sie eine WrapPanel
benötigen, ein Layout-Panel, mit dem Elemente gefüllt werden können, bis sie eine Kante erreicht haben. An diesem Punkt fließen die verbleibenden Elemente in die nächste Zeile. Aber Sie möchten immer noch eine ItemsControl
verwenden, damit Sie alle Vorteile der Datenbindung und dynamischen Generierung erhalten können. Deshalb werden wir die ItemsControl.ItemsPanel
Eigenschaft verwenden, die es uns ermöglicht, das Panel anzugeben, in das die Elemente eingefügt werden. Beginnen wir mit der Code-behind wieder von vorn anfangen:
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; }
}
Nicht viel hat sich hier geändert, aber ich habe die Beispielfelder bearbeitet, um besser Ihrem Beispiel zu entsprechen. Nun wollen wir sehen, wo die Magie happens- die XAML für die Window
:
<Window x:Class="DataBoundFields.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
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="{Binding Name}" VerticalAlignment="Center"/>
<TextBox Width="{Binding Length}" Margin="5,0,0,0"/>
<Label Content="*" Visibility="{Binding Required, Converter={StaticResource BoolToVisConverter}}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"
Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=ActualHeight}"
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=ActualWidth}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
Zunächst werden Sie feststellen, dass die ItemTemplate
leicht verändert hat. Das Label ist immer noch an die Eigenschaft name gebunden, aber jetzt ist die Breite des Textfelds an die length -Eigenschaft gebunden (so können Sie Textboxen unterschiedlicher Länge haben). Darüber hinaus habe ich ein "*" zu allen Feldern hinzugefügt, die benötigt werden, mit einer vereinfachten BoolToVisibilityConverter
(wo Sie den Code überall finden können, und ich werde hier nicht posten).
Die Hauptsache ist die Verwendung einer WrapPanel
in der ItemsPanel
Eigenschaft unserer ListBox
. Dies sagt der ListBox
, dass alle Elemente, die es erzeugt, in ein horizontal gewundenes Layout (das entspricht Ihrem Screenshot) geschoben werden müssen. Was diese Arbeit noch besser macht, ist die Höhe und die Breite, die auf dem Panel gebunden werden - was das sagt, "mache dieses Panel zur gleichen Größe wie mein Elternfenster." Das bedeutet, dass, wenn ich die Größe Window
, die WrapPanel
passt seine Größe entsprechend, was zu einem besseren Layout für die Elemente. Die beiden Screenshots hier zeigen dies:
alt text http://img156.imageshack.us/img156/6849/wrappanelfields.png
alt text http://img12.imageshack.us/img12/2426/wrappanelfields2.png
+1, aber ich denke, das OP wollte Länge und Erforderlich, um die Eingabe zu beschränken. –
Natürlich, aber ich bin nicht sicher, wie genau er diese Einschränkungen verwenden will, also habe ich es einfach ohne sie verlassen. – Charlie
Problem ist - und ich habe wahrscheinlich verwirrt, indem Sie den Variablennamen "MyGrid" -Ich füge diese zu einem , kein DataGrid.Dies ist ein Dateneingabeformular, das ich in einer bestimmten Reihenfolge herausgeben muss.Es könnte 3 Label sein/textbox combminations mit texboxes unterschiedlicher Länge in einer Zeile und 10 in der nächsten Zeile. Es gibt verschiedene Versionen dieses Formulars, warum die Felder aus der Datenbank geladen werden, und warum ich es dynamisch nennen. So tut es nicht passen gut in ein DataGrid-Layout und deshalb habe ich versucht, sie dynamisch zu erstellen.Sagen, ich habe ein anderes Feld im Objekt - LastFieldOnLine, um neue Zeile –
user210757