tutorial style que ejemplos wpf dynamic controls

style - wpf templates



Agregar programáticamente controles al formulario WPF (3)

Bien, segunda vez es el encanto. Según su captura de pantalla de diseño, puedo inferir de inmediato que lo que necesita es un WrapPanel , un panel de diseño que permite que los artículos se llenen hasta que llegue a un borde, momento en el que los elementos restantes fluyen a la siguiente línea. Pero aún desea utilizar un ItemsControl para que pueda obtener todos los beneficios de la generación dinámica y vinculante de datos. Así que para esto vamos a usar la propiedad ItemsControl.ItemsPanel , que nos permite especificar el panel en el que se colocarán los elementos. Comencemos con el código detrás de nuevo:

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

No ha cambiado mucho aquí, pero he editado los campos de muestra para que coincidan mejor con su ejemplo. Ahora veamos dónde sucede la magia: el XAML para la 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>

Primero, notará que ItemTemplate ha cambiado ligeramente. La etiqueta todavía está vinculada a la propiedad de nombre, pero ahora el ancho del cuadro de texto está vinculado a la propiedad de longitud (por lo que puede tener cuadros de texto de longitud variable). Además, he agregado un "*" a cualquier campo que se requiera, usando un BoolToVisibilityConverter simplista (que puede encontrar el código para cualquier lugar, y no lo publicaré aquí).

Lo principal que hay que notar es el uso de un WrapPanel en la propiedad ItemsPanel de nuestro ListBox . Esto le dice al ListBox que cualquier elemento que genere debe ser insertado en un diseño horizontal envuelto (esto coincide con su captura de pantalla). Lo que hace que este trabajo sea aún mejor es el enlace de alto y ancho en el panel, lo que dice es "hacer que este panel tenga el mismo tamaño que mi ventana principal". Eso significa que cuando redimensionar la Window , el WrapPanel ajusta su tamaño en consecuencia, lo que resulta en una mejor disposición de los elementos. Las dos capturas de pantalla aquí demuestran esto:

texto alternativo http://img156.imageshack.us/img156/6849/wrappanelfields.png

texto alternativo http://img12.imageshack.us/img12/2426/wrappanelfields2.png

Estoy tratando de agregar controles a un UserControl dinámicamente (programáticamente). Obtengo una lista genérica de objetos de mi Business Layer (recuperada de la base de datos) y para cada objeto, deseo agregar una etiqueta y un TextBox al UserControl de WPF y establecer la posición y el ancho para que se vea bien, y con suerte aprovecha las capacidades de Validación de WPF. Esto es algo que sería fácil en la programación de Windows Forms, pero soy nuevo en WPF. ¿Cómo hago esto? (Ver comentarios para las preguntas) Diga que este es mi objetivo:

public class Field { public string Name { get; set; } public int Length { get; set; } public bool Required { get; set; } }

Luego, en mi WPF UserControl, intento crear una etiqueta y un cuadro de texto para cada objeto:

public void createControls() { List<Field> fields = businessObj.getFields(); Label label = null; TextBox textbox = null; foreach (Field field in fields) { label = new Label(); // HOW TO set text, x and y (margin), width, validation based upon object? // i have tried this without luck: // Binding b = new Binding("Name"); // BindingOperations.SetBinding(label, Label.ContentProperty, b); MyGrid.Children.Add(label); textbox = new TextBox(); // ??? MyGrid.Children.Add(textbox); } // databind? this.DataContext = fields; }


Escucharía las respuestas de Charlie y Jobi, pero para responder la pregunta directamente ... (Cómo agregar controles y ubicarlos manualmente).

Use un control Canvas , en lugar de una Grid . Los lienzos dan al control una cantidad infinita de espacio y te permiten colocarlos manualmente. Utiliza propiedades adjuntas para realizar un seguimiento de la posición. En el código, se vería así:

var tb = new TextBox(); myCanvas.Children.Add(tb); tb.Width = 100; Canvas.SetLeft(tb, 50); Canvas.SetTop(tb, 20);

En XAML ...

<Canvas> <TextBox Width="100" Canvas.Left="50" Canvas.Top="20" /> </Canvas>

También puede colocarlos en relación con los bordes derecho e inferior. Al especificar tanto una parte superior como una parte inferior, el control cambiará de tamaño verticalmente con el lienzo. Del mismo modo para Izquierda y Derecha.


No se recomienda agregar controles como este. Lo que idealmente haría en WPF es poner un ListBox (o ItemsControl) y vincular su colección de objetos Business como la propiedad itemsControl.ItemsSource. Ahora defina DataTemplate en XAML para su tipo DataObject y estará listo, esa es la magia de WPF.

Las personas que provienen de un entorno de winforms tienden a hacer de la manera descrita y que no es la correcta en WPF.