2010-03-08 8 views
13

Tengo un formulario WPF, quiero diseñar un formulario estándar en él. Cada elemento de formulario tendrá una etiqueta y luego un control. Bastante estándar.¿Cómo diseño un formulario en WPF usando la cuadrícula u otros controles para su mantenimiento?

Si uso un panel de envoltura, puede hacer que la etiqueta y el control se separen, pero quiero que permanezcan juntos. ¿Hay algún equivalente de WPF de <nobr/>?

La cuadrícula funciona, y permite la extensión de columnas, etc., sin embargo, realmente odio que especifique la columna y la fila en cada control. Esto hace que sea extremadamente incómodo reordenar o insertar cosas en la lista.

¿Hay alguna manera de hacer que la cuadrícula use más columnas/filas de estilo HTML donde los elementos son secundarios de la fila en la que se encuentran, para que pueda volver a pedirlos fácilmente?

¿Hay algún otro control que me permita diseñar un formulario fácilmente?

Respuesta

19

¿Hay algún equivalente WPF de nobr?

Recuerde que puede paneles de nido:

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

Además, para los diseños de columnas, el alcance tamaño compartida de la cuadrícula puede coordinar cualquier número de cuadrículas que lo utilizan:

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

Odio lo detallado que es el XAML para esto, especialmente que tienes que repetir las definiciones de las columnas. Sin embargo, si estructuras tus clases adecuadamente y usas plantillas, no es tan terrible. Y tenga en cuenta que no realiza un seguimiento de los números de fila en ningún lugar de este esquema, por lo que volver a ordenar los campos es simple.

+0

buena solución, pero es grosero cuánto XAML necesita. ¿Y qué hay del rendimiento? – GorillaApe

4

Pruebe el control UniformGrid.

4

Lo que podría estar buscando es un panel de pila. El uso de un StackPanel vertical le permitirá organizar su etiqueta y controles de manera consistente. Para cada etiqueta y el control es posible que desee un panel pila horizontal al igual que

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

ya se puede agregar, eliminar, editar y reordenar a su antojo sin tener que preocuparse acerca de las columnas y filas.

+0

Puede ser para una mejor sintaxis, ponga los anchos en StackPanel.Resources. –

1

Si puede acordarlo, recomiendo Expression Blend si va a hacer mucho diseño de interfaz de usuario. Permite una vista más simple de los artículos. Anidar controles en varios contenedores es una buena forma de que la UI sea dinámica, pero estructurada.

Normalmente utilizaré un panel de cuadrícula para dividir una ventana en áreas funcionales. Luego usaré una serie de StackPanels (a menudo un panel de pila vertical con StackPanels horizontales dentro de él, cada uno con una etiqueta y un cuadro de texto).

Desafortunadamente las rejillas solo funcionan como usted indicó. Los elementos en ellos especifican la fila y/o columna en la que residen. Si usó Mezclar, agregar columnas de cuadrícula o Filas tendrá controles que cambien automáticamente la especificación de fila/columna para mantenerse en la posición en la que se colocaron.

Espero que ayude.

Expression Blend Trial en Microsoft.

ACTUALIZACIÓN:

VS2012 tiene una gran cantidad de la funcionalidad de Expression Blend al horno en el diseñador WPF. Gran parte de la necesidad de una copia de Blend ya no existe, ya que los desarrolladores tienen acceso a muchas de las geniales herramientas de Blend.

2

Echa un vistazo a las cosas de Karl.

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

simple y limpia 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

Buen código de aspecto. Pero el control fue escrito en VB.NET. ¿Sabes lo mismo, pero en C#? –

+0

Parece que el sitio anterior ya no existe. –

0

En nuestro producto se utiliza un HeaderedContentControl para diseñar formas en una cuadrícula. La plantilla de control tiene una etiqueta y relleno/márgenes para que el contenido del control esté siempre espaciado apropiadamente. En el XAML, simplemente los agregamos en las columnas.

Publicaba algo de XAML, pero estoy en el medio de configurar una nueva computadora. : | Pero de lo que recuerdo se vería algo como esto:

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

Luego, en la red, a definir sus filas y columnas, y poner uno de estos en cada célula, o justo al final de cada fila:

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

Podría estar respondiendo una pregunta diferente, pero así es como diseñamos nuestros formularios.

2

Here is a library for it

xaml muestra:

<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 un markupextension que devuelve un WPF vainilla Grid para un buen árbol visual superficial.

NuGet

0

me encontré con este post de hoy mientras que tener la misma pregunta, usando las respuestas en este hilo se me ocurrió una solución manejable para pares de texto/texto simple. Para agregar nuevos campos, simplemente expanda la colección "FormItems".

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

No ha habido ninguna consideración por márgenes y el relleno, sólo se muestra el concepto de usar un DataTemplate para reutilizar el diseño de cada elemento. Se puede adaptar para incluir otros tipos de datos y controles con bastante facilidad. Incluso podría usar el ItemTemplateSelector para seleccionar una plantilla diferente según el tipo de DictionaryEntry.Valor

EDITAR

Otro enfoque que he encontrado que hizo más fácil para DataBinding era utilizar Visual Studio para crear un nuevo WPF "control personalizado". Al hacerlo, se creará un nuevo archivo llamado Themes/Generic.xaml con un nuevo diseño predeterminado definido allí. Algunas ediciones simples y podemos usar ItemsControl para mostrar nuestro nuevo control.

Nueva clase:

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

Temas/Generic.xaml: ejemplo

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

Uso:

<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

Cuestiones relacionadas