Dobra, po raz drugi urok. W oparciu o zrzut ekranu układu mogę od razu wywnioskować, że potrzebny jest WrapPanel
, panel układu, który pozwala elementom wypełnić się, aż osiągnie krawędź, w którym to momencie pozostałe elementy przepływają do następnej linii. Ale nadal chcesz korzystać z ItemsControl
, aby uzyskać wszystkie korzyści związane z wiązaniem danych i generowaniem dynamicznym. W tym celu użyjemy właściwości ItemsControl.ItemsPanel
, która pozwala nam określić panel, w którym zostaną umieszczone elementy. Zacznijmy opóźnieniem kodu ponownie:
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; }
}
Niewiele zmieniło się tu, ale już edycja pól próbnych, aby lepiej dopasować swój przykład. Teraz przyjrzyjmy się, gdzie magia happens- XAML dla 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>
Po pierwsze, można zauważyć, że ItemTemplate
zmieniła się nieznacznie. Etykieta jest nadal powiązana z właściwością name, ale teraz szerokość textbox jest powiązana z właściwością length (więc możesz mieć pola tekstowe o różnej długości). Co więcej, dodałem "*" do wszystkich wymaganych pól, używając uproszczonego BoolToVisibilityConverter
(którego kod można znaleźć w dowolnym miejscu i nie będę tu publikować).
Najważniejszą rzeczą, którą należy zauważyć, jest użycie WrapPanel
w obiekcie ItemsPanel
naszego . To mówi ListBox
, że wszelkie elementy, które generuje, muszą być wciśnięte w poziomy układ zawinięty (to pasuje do zrzutu ekranu). Co sprawia, że praca ta jest jeszcze lepsza, to wiążąca się wysokość i szerokość na panelu - jak to się mówi, "ustaw ten panel na taki sam rozmiar jak moje okno nadrzędne". Oznacza to, że gdy zmieniam rozmiar Window
, WrapPanel
dostosowuje odpowiednio swój rozmiar, co daje lepszy układ elementów. Te dwa screenshoty tutaj wykazać to:
alt text http://img156.imageshack.us/img156/6849/wrappanelfields.png
alt text http://img12.imageshack.us/img12/2426/wrappanelfields2.png
+1, ale myślę, że OP chciał Długość i Wymagane, aby ograniczyć wejście. –
Oczywiście, ale nie jestem pewien, jak dokładnie on chce wykorzystać te ograniczenia, więc po prostu zostawiłem to bez nich. – Charlie
Kłopot jest - i prawdopodobnie pomieszałem sprawy, używając nazwy zmiennej "MyGrid" - dodam te do , a nie do DataGrid. Jest to formularz wprowadzania danych, który muszę podać w określonej kolejności.Może to być 3 etykieta/combminations textbox z texboksami o różnych długościach w jednym wierszu i 10 w następnym wierszu.Istnieją różne wersje tego formularza, dlatego pola są ładowane z bazy danych i dlaczego nazywam to dynamic.So to nie dobrze pasuje do układu DataGrid i dlatego próbowałem ich dynamicznie tworzyć. Jeśli mam inne pole w obiekcie - LastFieldOnLine do wyznaczenia nowej linii –
user210757