2010-03-08 7 views
13

Ich habe ein WPF-Formular, ich möchte ein Standardformular darauf legen. Jedes Formularelement hat eine Bezeichnung und dann ein Steuerelement. Ziemlich normales Zeug.Wie laye ich ein Formular in WPF mit Raster oder anderen Steuerelementen für die Wartbarkeit

Wenn ich ein Wrap-Panel verwende, kann dies dazu führen, dass das Label und das Steuerelement getrennt werden, aber ich möchte, dass sie zusammen bleiben. Gibt es ein WPF-Äquivalent von <nobr/>?

Grid funktioniert, und ermöglicht Spalte spannen etc, aber ich wirklich hasse es, dass Sie die Spalte und Zeile auf jedem Steuerelement angeben. Dies macht es äußerst umständlich, Dinge in der Liste neu anzuordnen oder einzufügen.

Gibt es eine Möglichkeit, das Gitter mehr HTML-Stil Spalten/Zeilen zu verwenden, wo die Elemente ein Kind der Zeile sind, in der sie sind, so dass ich leicht neu bestellen kann?

Gibt es ein anderes Steuerelement, mit dem ich leicht ein Formular erstellen kann?

Antwort

19

gibt es einige WPF Äquivalent von Nobr?

Denken Sie daran, dass Sie nisten Platten:

<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> 

Auch für säulen Layouts, das gemeinsame Größe Umfang der Gitter eine beliebige Anzahl von Gittern koordinieren können, die sie verwenden:

<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> 

Ich hasse es, wie ausführlich der XAML dafür ist, besonders, dass Sie die Spaltendefinitionen wiederholen müssen. Obwohl, wenn Sie Ihre Klassen richtig strukturieren und Vorlagen verwenden, ist es nicht so schlimm. Beachten Sie, dass Sie die Zeilennummern nirgendwo in diesem Schema nachverfolgen, daher ist das Neuanordnen von Feldern einfach.

+0

nette Lösung, aber es ist unhöflich, wie viel XAML Sie brauchen. Und was ist mit der Leistung? – GorillaApe

4

Versuchen Sie das UniformGrid-Steuerelement.

4

Was Sie möglicherweise suchen, ist ein Stack-Panel. Wenn Sie ein vertikales StackPanel verwenden, können Sie Label und Steuerelemente einheitlich anordnen. Für jedes Etikett und Kontrolle, die Sie könnten

<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> 

Jetzt können Sie hinzufügen, löschen, zu bearbeiten, wie so eine horizontale Stapelplatte wollen und Inhalt Ihres Herzens neu ordnen, ohne Spalten und Zeilen sich darum zu kümmern.

+0

Kann für bessere Syntax sein, legen Sie die Breiten in StackPanel.Resources. –

1

Wenn Sie es können, empfehle ich Expression Blend, wenn Sie viel UI-Design tun werden. Es ermöglicht eine einfachere Ansicht der Elemente. Das Verschachteln von Steuerelementen in verschiedene Container ist eine gute Möglichkeit, die Benutzeroberfläche dynamisch, aber strukturiert zu gestalten.

Normalerweise verwende ich ein Rasterfeld, um ein Fenster in Funktionsbereiche aufzuteilen. Dann verwende ich eine Reihe von StackPanels (oft ein vertikales Stack Panel mit horizontalen StackPanels, jedes mit einem Label und einem Textfeld).

Leider funktionieren Grids nur wie Sie angegeben haben. Elemente in ihnen geben die Zeile und/oder Spalte an, in der sie sich befinden. Wenn Sie die Option Überblenden verwenden, ändert das Hinzufügen von Rasterspalten oder Zeilen automatisch die Zeilen-/Spaltenspezifikation, um an der Position zu bleiben, an der sie platziert wurden.

Ich hoffe, es hilft.

Expression Blend Trial bei Microsoft.

UPDATE:

VS2012 hat eine Menge der Expression Blend-Funktionalität in den WPF-Designer gebacken. Viel von der Notwendigkeit einer Kopie von Blend ist nicht mehr da, da Entwickler Zugriff auf viele der coolen Tools von Blend haben.

2

Schau dir Karls Sachen an.

http://web.archive.org/web/20150620104259/https://karlshifflett.wordpress.com/2008/10/23/wpf-silverlight-lob-form-layout-searching-for-a-better-solution/

Einfach und sauber 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> 
+0

Gut aussehender Code. Aber die Kontrolle wurde in VB.NET geschrieben. Kennst du das Gleiche, aber in C#? –

+0

Es sieht so aus, als ob die obige Seite nicht mehr existiert. –

0

In unserem Produkt verwenden wir eine HeaderedContentControl Formen in einem Raster anzulegen. Die Steuerelementvorlage hat eine Beschriftung und Auffüllung/Ränder, so dass der Inhalt des Steuerelements immer angemessen beabstandet ist. Im XAML fügen wir sie einfach in die Spalten ein.

Ich würde etwas XAML posten, aber ich bin gerade dabei, einen neuen Computer einzurichten. : | Aber von dem, was ich mich erinnern würde es wie folgt aussehen:

<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> 

Dann im Raster definieren Sie Ihre Zeilen und Spalten, und in jeder Zelle eine von diesen setzen, oder einfach nur nach unten jede Zeile:

<HeaderedContentControl x:Name="username" Grid.Column=0 Content="User Name" Tag=textboxUserName> 
<Textbox x:Name=textboxUserName> 
</HeaderedContentControl> 

Ich könnte eine andere Frage beantworten, aber so legen wir unsere Formulare aus.

2

Here is a library for it

Probe xAML:

<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> 
    ... 

Es ist eine Markupextension, die eine Vanille WPF Grid für eine schöne flache visuelle Struktur zurückzugibt.

NuGet

0

ich auf diesen Beitrag kam heute, während die gleiche Frage haben, die Antworten in diesem Thread mit ich mit einer überschaubaren Lösung zu einfachen Text/Textpaare aufkam. Um neue Felder hinzuzufügen, erweitern Sie einfach die Sammlung "FormItems".

xmlns: c = "clr-namespace: System.Collections; Montage = 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> 

Basic Form Layout Result

Es gibt keine Rücksicht auf die Margen und Polsterung gewesen ist, es zeigt nur das Konzept Verwenden eines DataTemplate, um das Layout jedes Elements wiederzuverwenden. Es kann relativ einfach angepasst werden, um andere Datentypen und Steuerelemente einzubeziehen. Sie können sogar den ItemTemplateSelector verwenden, um basierend auf dem Typ des DictionaryEntry eine andere Vorlage auszuwählen.Wert

EDIT

Ein anderer Ansatz, fand ich, dass es einfacher für Databinding Visual Studio zu verwenden, war eine neue WPF „Custom Control“ zu erstellen. Dadurch wird eine neue Datei mit dem Namen Designs/Generic.xaml mit einem neuen Standardlayout erstellt. Ein paar einfache Änderungen und wir können das ItemsControl verwenden, um unser neues Steuerelement anzuzeigen.

Neue Klasse:

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()); 
} 

Themen/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> 

Anwendungsbeispiel:

<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> 

Custom Control Layout Result

Verwandte Themen