Para ver el artículo en inglés, active la casilla Inglés. También puede ver el texto en inglés en una ventana emergente si pasa el puntero del mouse por el texto.
Traducción
Inglés

Información general sobre elementos Panel

 

Publicada: junio de 2016

Los elementos Panel son componentes que controlan la representación de los elementos: su tamaño y dimensiones, su posición y la disposición de su contenido secundario. Windows Presentation Foundation (WPF) proporciona varios elementos Panel predefinidos, así como la posibilidad de construir elementos Panel personalizados.

Este tema contiene las secciones siguientes.

Panel es la clase base para todos los elementos que proporcionan la compatibilidad de diseño en Windows Presentation Foundation (WPF). Los elementos Panel derivados se utilizan para colocar y organizar elementos en Lenguaje XAML (Extensible Application Markup Language) y en el código.

WPF incluye un conjunto completo de implementaciones de panel derivadas que permiten numerosos diseños complejos. Estas clases derivadas exponen propiedades y métodos que habilitan la mayoría de los escenarios de interfaz de usuario (UI) estándar. Los programadores que no encuentren un comportamiento de disposición secundario acorde con sus necesidades pueden crear diseños nuevos que invaliden los métodos ArrangeOverride y MeasureOverride. Para obtener más información sobre los comportamientos de diseño personalizados, vea Elementos Panel personalizados.

Todos los elementos Panel son compatibles con las propiedades básicas de posición y dimensionamiento definidas por FrameworkElement, como son Height, Width, HorizontalAlignment, VerticalAlignment, Margin y LayoutTransform. Para obtener información adicional sobre las propiedades de posición definidas por FrameworkElement, vea Información general sobre alineación, márgenes y relleno.

Panel expone propiedades adicionales que son de importancia crítica para entender y utilizar el diseño. La propiedad Background se utiliza para rellenar el área existente entre los límites de un elemento de panel derivado con un objeto Brush. Children representa la colección secundaria de elementos que forman el elemento Panel. InternalChildren representa el contenido de la colección Children junto con los miembros generados mediante el enlace de datos. Ambos se componen de una colección UIElementCollection de elementos secundarios hospedados en el elemento Panel primario.

El panel también expone una propiedad adjunta Panel.ZIndex que se puede utilizar para lograr un orden dispuesto en capas en un elemento Panel derivado. Los miembros de la colección Children de un panel cuyo valor de Panel.ZIndex es mayor aparecen delante de los que tienen un valor de Panel.ZIndex menor. Esto es especialmente útil para los paneles como Canvas y Grid, que permiten a los elementos secundarios compartir el mismo espacio de coordenadas.

Panel también define el método OnRender, que se puede utilizar para invalidar el comportamiento de presentación predeterminado de un elemento Panel.

Los elementos de panel derivados utilizan mucho las propiedades adjuntas. Una propiedad adjunta es una forma especializada de propiedad de dependencia que no tiene el "contenedor" de propiedades de Common Language Runtime (CLR) convencional. Las propiedades adjuntas tienen una sintaxis especializada en Lenguaje XAML (Extensible Application Markup Language), que se puede ver en algunos de los ejemplos que siguen.

Uno de los propósitos de una propiedad adjunta es permitir a los elementos secundarios almacenar valores únicos de una propiedad que en realidad está definida por un elemento principal. Una aplicación de esta funcionalidad consiste en tener elementos secundarios que informen al elemento primario sobre cómo desean ser presentados en la interfaz de usuario (UI), lo que resulta sumamente útil para el diseño de la aplicación. Para obtener más información, vea Información general sobre propiedades asociadas.

Muchos objetos se derivan de Panel, pero no todos ellos están pensados para usarlos como proveedores de diseño raíz. Existen seis clases de panel definidas (Canvas, DockPanel, Grid, StackPanel, VirtualizingStackPanel y WrapPanel) que están diseñadas específicamente para crear la IU de las aplicaciones.

Cada elemento de panel encapsula su propia funcionalidad especial, como se muestra en la tabla siguiente.

Nombre del elemento

¿Es un panel de interfaz de usuario?

Descripción

Canvas

Si

Define un área en la que pueden colocarse explícitamente los elementos secundarios utilizando las coordenadas relativas al área del control Canvas.

DockPanel

Si

Define un área en la que se pueden organizar horizontal o verticalmente los elementos secundarios, uno respecto al otro.

Grid

Si

Define un área de cuadrícula flexible que se compone de columnas y filas. Los elementos secundarios de un control Grid se pueden colocar con precisión utilizando la propiedad Margin.

StackPanel

Si

Organiza los elementos secundarios en una única línea que se puede orientar horizontal o verticalmente.

TabPanel

No

Controla el diseño de los botones de las fichas de un control TabControl.

ToolBarOverflowPanel

No

Organiza el contenido dentro de un control ToolBar.

UniformGrid

No

UniformGrid se utiliza para organizar los elementos secundarios en una cuadrícula cuyas celdas tienen todas el mismo tamaño.

VirtualizingPanel

No

Proporciona una clase base para los paneles que pueden "virtualizar" su colección de elementos secundarios.

VirtualizingStackPanel

Si

Organiza y virtualiza el contenido en una sola línea orientada horizontal o verticalmente.

WrapPanel

Si

WrapPanel organiza los elementos secundarios secuencialmente de izquierda a derecha y traslada el contenido a la línea siguiente cuando alcanza el borde del cuadro contenedor. La clasificación siguiente se realiza secuencialmente de arriba abajo o de izquierda a derecha, en función del valor de la propiedad Orientation.

Existen seis clases de paneles disponibles en WPF que están optimizadas para admitir los escenarios de la IU: Canvas, DockPanel, Grid, StackPanel, VirtualizingStackPanel y WrapPanel. Estos elementos de panel son fáciles utilizar, versátiles y suficientemente extensibles para la mayoría de las aplicaciones.

Cada elemento Panel derivado trata las restricciones de tamaño de forma distinta. La comprensión del modo en que un elemento Panel controla las restricciones en la dirección horizontal o vertical puede hacer que el diseño sea más predecible.

Nombre del panel

Dimensión x

Dimensión y

Canvas

Restringida al contenido

Restringida al contenido

DockPanel

Restringida

Restringida

StackPanel (Orientación vertical)

Restringida

Restringida al contenido

StackPanel (Orientación horizontal)

Restringida al contenido

Restringida

Grid

Restringida

Restringida, excepto en los casos en que Auto se aplica a las filas y las columnas

WrapPanel

Restringida al contenido

Restringida al contenido

A continuación se ofrecen descripciones más detalladas y ejemplos del uso de cada uno de estos elementos.

El elemento Canvas permite la colocación del contenido de acuerdo con unas coordenadas x e y absolutas. Los elementos se pueden dibujar en una ubicación única; o, si ocupan las mismas coordenadas, el orden en que aparecen en el marcado determina el orden en el que se dibujan.

Canvas proporciona la compatibilidad de diseño más flexible de todos los elementos Panel. Las propiedades Height y Width se utilizan para definir el área del lienzo, y a los elementos que contiene se les asignan coordenadas absolutas relativas al área del elemento Canvas primario. Cuatro propiedades adjuntas, Canvas.Left, Canvas.Top, Canvas.Right y Canvas.Bottom, permiten obtener un control muy preciso de la posición de los objetos dentro de un elemento Canvas, y gracias a ellas el programador puede colocar y organizar con precisión los elementos en la pantalla.

Canvas puede colocar los elementos secundarios en cualquier posición de la pantalla, incluso en coordenadas situadas fuera de sus propias dimensiones, definidas mediante Height y Width. Además, el tamaño de sus propios elementos secundarios no afecta a Canvas. Como resultado, es posible que un elemento secundario se dibuje sobre otros elementos situados fuera del rectángulo delimitador del elemento Canvas primario. El comportamiento predeterminado de un elemento Canvas es permitir que se dibujen elementos secundarios fuera de los límites del elemento Canvas primario. Si no desea que esto ocurra, puede establecer la propiedad ClipToBounds en true. Esto hace que Canvas se recorte a su propio tamaño. Canvas es el único elemento de diseño que permite dibujar los elementos secundarios fuera sus límites.

Este comportamiento se muestra gráficamente en Width Properties Comparison Sample.

Es posible crear instancias de un elemento Canvas simplemente con Lenguaje XAML (Extensible Application Markup Language) o mediante código. En el ejemplo siguiente se muestra cómo utilizar Canvas para colocar el contenido de forma absoluta. Este código genera tres cuadrados de 100 píxeles. El primer cuadrado es rojo y su posición superior izquierda (x, y) se especifica como (0, 0). El segundo cuadrado es verde y su posición superior izquierda es (100, 100), que es inmediatamente debajo y a la derecha del primer cuadrado. El tercer cuadrado es azul y su posición superior izquierda es (50, 50), por lo que cubre el cuadrante inferior derecho del primer cuadrado y el cuadrante superior izquierdo del segundo. Dado que el tercer cuadrado se coloca en último lugar, parece que está encima de los otros dos cuadrados; es decir, las partes que se superponen adoptan el color del tercer cuadrado.


// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "Canvas Sample";

// Create the Canvas
myParentCanvas = new Canvas();
myParentCanvas.Width = 400;
myParentCanvas.Height = 400;

// Define child Canvas elements
myCanvas1 = new Canvas();
myCanvas1.Background = Brushes.Red;
myCanvas1.Height = 100;
myCanvas1.Width = 100;
Canvas.SetTop(myCanvas1, 0);
Canvas.SetLeft(myCanvas1, 0);

myCanvas2 = new Canvas();
myCanvas2.Background = Brushes.Green;
myCanvas2.Height = 100;
myCanvas2.Width = 100;
Canvas.SetTop(myCanvas2, 100);
Canvas.SetLeft(myCanvas2, 100);

myCanvas3 = new Canvas();
myCanvas3.Background = Brushes.Blue;
myCanvas3.Height = 100;
myCanvas3.Width = 100;
Canvas.SetTop(myCanvas3, 50);
Canvas.SetLeft(myCanvas3, 50);

// Add child elements to the Canvas' Children collection
myParentCanvas.Children.Add(myCanvas1);
myParentCanvas.Children.Add(myCanvas2);
myParentCanvas.Children.Add(myCanvas3);

// Add the parent Canvas as the Content of the Window Object
mainWindow.Content = myParentCanvas;
mainWindow.Show ();

<Page WindowTitle="Canvas Sample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <Canvas Height="400" Width="400">
    <Canvas Height="100" Width="100" Top="0" Left="0" Background="Red"/>
    <Canvas Height="100" Width="100" Top="100" Left="100" Background="Green"/>
    <Canvas Height="100" Width="100" Top="50" Left="50" Background="Blue"/>
  </Canvas>
</Page>

La aplicación compilada produce una nueva IU con esta apariencia.

Elemento Canvas típico.

El elemento DockPanel utiliza la propiedad adjunta DockPanel.Dock tal y como está establecida en los elementos de contenido secundarios para colocar el contenido a lo largo de los bordes de un contenedor. Cuando DockPanel.Dock se establece en Top o Bottom, coloca los elementos secundarios por encima o por debajo de los demás. Cuando la propiedad DockPanel.Dock está establecida en Left o en Right, coloca los elementos secundarios a la izquierda o a la derecha de los demás. La propiedad LastChildFill determina la posición del último elemento agregado como un elemento secundario de un elemento DockPanel.

Puede utilizar DockPanel para colocar un grupo de controles relacionados, como un conjunto de botones. También puede utilizarlo para crear una IU "con paneles", similar a la de Microsoft Outlook.

Si no se especifican las propiedades Height y Width, DockPanel se ajusta a su contenido. Su tamaño puede aumentar o disminuir de acuerdo con el tamaño de sus elementos secundarios. Sin embargo, cuando se especifican estas propiedades y ya no hay sitio para el siguiente elemento secundario especificado, DockPanel no muestra ese elemento secundario ni los elementos secundarios subsiguientes, y no mide los elementos secundarios subsiguientes.

De forma predeterminada, el último elemento secundario de un elemento DockPanel "rellenará" el espacio restante que quede sin asignar. Si no desea que esto ocurra, establezca la propiedad LastChildFill en false.

En el ejemplo siguiente se muestra cómo dividir el espacio mediante DockPanel. Se agregan cinco elementos Border como elementos secundarios de un elemento DockPanel primario. Cada uno de ellos utiliza una propiedad de posición diferente de un elemento DockPanel para dividir el espacio. El último elemento "rellena" el espacio que queda sin asignar.


// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "DockPanel Sample";

// Create the DockPanel
DockPanel myDockPanel = new DockPanel();
myDockPanel.LastChildFill = true;

// Define the child content
Border myBorder1 = new Border();
myBorder1.Height = 25;
myBorder1.Background = Brushes.SkyBlue;
myBorder1.BorderBrush = Brushes.Black;
myBorder1.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder1, Dock.Top);
TextBlock myTextBlock1 = new TextBlock();
myTextBlock1.Foreground = Brushes.Black;
myTextBlock1.Text = "Dock = Top";
myBorder1.Child = myTextBlock1;

Border myBorder2 = new Border();
myBorder2.Height = 25;
myBorder2.Background = Brushes.SkyBlue;
myBorder2.BorderBrush = Brushes.Black;
myBorder2.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder2, Dock.Top);
TextBlock myTextBlock2 = new TextBlock();
myTextBlock2.Foreground = Brushes.Black;
myTextBlock2.Text = "Dock = Top";
myBorder2.Child = myTextBlock2;

Border myBorder3 = new Border();
myBorder3.Height = 25;
myBorder3.Background = Brushes.LemonChiffon;
myBorder3.BorderBrush = Brushes.Black;
myBorder3.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder3, Dock.Bottom);
TextBlock myTextBlock3 = new TextBlock();
myTextBlock3.Foreground = Brushes.Black;
myTextBlock3.Text = "Dock = Bottom";
myBorder3.Child = myTextBlock3;

Border myBorder4 = new Border();
myBorder4.Width = 200;
myBorder4.Background = Brushes.PaleGreen;
myBorder4.BorderBrush = Brushes.Black;
myBorder4.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder4, Dock.Left);
TextBlock myTextBlock4 = new TextBlock();
myTextBlock4.Foreground = Brushes.Black;
myTextBlock4.Text = "Dock = Left";
myBorder4.Child = myTextBlock4;

Border myBorder5 = new Border();
myBorder5.Background = Brushes.White;
myBorder5.BorderBrush = Brushes.Black;
myBorder5.BorderThickness = new Thickness(1);
TextBlock myTextBlock5 = new TextBlock();
myTextBlock5.Foreground = Brushes.Black;
myTextBlock5.Text = "This content will Fill the remaining space";
myBorder5.Child = myTextBlock5;


// Add child elements to the DockPanel Children collection
myDockPanel.Children.Add(myBorder1);
myDockPanel.Children.Add(myBorder2);
myDockPanel.Children.Add(myBorder3);
myDockPanel.Children.Add(myBorder4);
myDockPanel.Children.Add(myBorder5);

// Add the parent Canvas as the Content of the Window Object
mainWindow.Content = myDockPanel;
mainWindow.Show ();

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowTitle="DockPanel Sample">
  <DockPanel LastChildFill="True">
    <Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
      <TextBlock Foreground="Black">Dock = "Top"</TextBlock>
    </Border>
    <Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
      <TextBlock Foreground="Black">Dock = "Top"</TextBlock>
    </Border>
    <Border Height="25" Background="LemonChiffon" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Bottom">
      <TextBlock Foreground="Black">Dock = "Bottom"</TextBlock>
    </Border>
    <Border Width="200" Background="PaleGreen" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Left">
      <TextBlock Foreground="Black">Dock = "Left"</TextBlock>
    </Border>
    <Border Background="White" BorderBrush="Black" BorderThickness="1">
      <TextBlock Foreground="Black">This content will "Fill" the remaining space</TextBlock>
    </Border>
  </DockPanel>
</Page>

La aplicación compilada produce una nueva IU con esta apariencia.

Escenario DockPanel típico.

El elemento Grid combina la funcionalidad de una posición absoluta y de un control de datos tabular. Grid permite colocar con facilidad elementos y aplicarles estilo. Con Grid podrá definir agrupaciones flexibles de filas y columnas, e incluso dispone de un mecanismo para compartir información de tamaño entre varios elementos Grid.

Table y Grid comparten funcionalidades comunes, pero cada elemento es más apropiado para determinados escenarios. Table se ha diseñado para su uso en contenido dinámico (vea Información general sobre documentos dinámicos para obtener más información sobre el contenido dinámico). Las cuadrículas son más apropiadas para formularios (básicamente, en cualquier lugar excepto en el contenido dinámico). Dentro de un FlowDocument, una Table admite los comportamientos del contenido dinámico, como la paginación, el ajuste dinámico de columnas y la selección de contenido, mientras que Grid no. Por su parte, Grid es más apropiado fuera de un FlowDocument por numerosas razones; una de ellas es que Grid agrega elementos basándose en un índice de fila y columna, y Table no. El elemento Grid permite la disposición en capas del contenido secundario, lo que permite que haya más de un elemento dentro de una sola "celda". Table no admite la disposición en capas. Los elementos secundarios de Grid se pueden colocar de manera absoluta en relación con el área de los límites de la "celda". Table no admite esta característica. Por último, Grid es más ligero que Table.

Las columnas y las filas definidas dentro de un elemento Grid pueden sacar partido del ajuste de tamaño mediante Star para distribuir el espacio restante de forma proporcional. Cuando se selecciona Star como el alto o el ancho de una fila o una columna, dicha columna o fila recibe una proporción ponderada del espacio restante disponible. Por el contrario, Auto distribuye el espacio de manera uniforme basándose en el tamaño del contenido de una columna o una fila. Este valor se expresa como * o 2* al utilizar Lenguaje XAML (Extensible Application Markup Language). En el primer caso, la fila o la columna recibiría una vez el espacio disponible, en el segundo caso, dos veces, y así sucesivamente. Combinando esta técnica para distribuir proporcionalmente el espacio con un valor para VerticalAlignment y HorizontalAlignment de Stretch, es posible dividir el espacio de diseño en un porcentaje del espacio de pantalla. Grid es el único panel de diseño en el que se puede distribuir el espacio de esta manera.

En el ejemplo siguiente se muestra cómo compilar una IU similar a la del cuadro de diálogo Ejecutar del menú Inicio de Windows.

La aplicación compilada produce una nueva IU con esta apariencia.

Elemento de cuadrícula típico.

Un elemento StackPanel le permite "apilar" los elementos en una dirección asignada. De forma predeterminada, los elementos se apilan en dirección vertical. Se puede utilizar la propiedad Orientation para controlar el flujo del contenido.

Aunque DockPanel también puede "apilar" elementos secundarios, DockPanel y StackPanel no generan resultados análogos en algunos escenarios de uso. Por ejemplo, el orden en el que se colocan los elementos secundarios puede afectar a su tamaño en un elemento DockPanel pero no en un elemento StackPanel. Esto se debe a que StackPanel mide en la dirección del apilado en PositiveInfinity, mientras que DockPanel mide solo el tamaño disponible.

En el ejemplo siguiente se muestra esta diferencia fundamental.


// Create the application's main window
mainWindow = new Window ();
mainWindow.Title = "StackPanel vs. DockPanel";

// Add root Grid
myGrid = new Grid();
myGrid.Width = 175;
myGrid.Height = 150;
RowDefinition myRowDef1 = new RowDefinition();
RowDefinition myRowDef2 = new RowDefinition();
myGrid.RowDefinitions.Add(myRowDef1);
myGrid.RowDefinitions.Add(myRowDef2);

// Define the DockPanel
myDockPanel = new DockPanel();
Grid.SetRow(myDockPanel, 0);

//Define an Image and Source
Image myImage = new Image();
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi.EndInit();
myImage.Source = bi;

Image myImage2 = new Image();
BitmapImage bi2 = new BitmapImage();
bi2.BeginInit();
bi2.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi2.EndInit();
myImage2.Source = bi2;

Image myImage3 = new Image();
BitmapImage bi3 = new BitmapImage();
bi3.BeginInit();
bi3.UriSource = new Uri("smiley_stackpanel.PNG", UriKind.Relative);
bi3.EndInit();
myImage3.Stretch = Stretch.Fill;
myImage3.Source = bi3;

// Add the images to the parent DockPanel
myDockPanel.Children.Add(myImage);
myDockPanel.Children.Add(myImage2);
myDockPanel.Children.Add(myImage3);

//Define a StackPanel
myStackPanel = new StackPanel();
myStackPanel.Orientation = Orientation.Horizontal;
Grid.SetRow(myStackPanel, 1);

Image myImage4 = new Image();
BitmapImage bi4 = new BitmapImage();
bi4.BeginInit();
bi4.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi4.EndInit();
myImage4.Source = bi4;

Image myImage5 = new Image();
BitmapImage bi5 = new BitmapImage();
bi5.BeginInit();
bi5.UriSource = new Uri("smiley_stackpanel.png", UriKind.Relative);
bi5.EndInit();
myImage5.Source = bi5;

Image myImage6 = new Image();
BitmapImage bi6 = new BitmapImage();
bi6.BeginInit();
bi6.UriSource = new Uri("smiley_stackpanel.PNG", UriKind.Relative);
bi6.EndInit();
myImage6.Stretch = Stretch.Fill;
myImage6.Source = bi6;

// Add the images to the parent StackPanel
myStackPanel.Children.Add(myImage4);
myStackPanel.Children.Add(myImage5);
myStackPanel.Children.Add(myImage6);

// Add the layout panels as children of the Grid
myGrid.Children.Add(myDockPanel);
myGrid.Children.Add(myStackPanel);

// Add the Grid as the Content of the Parent Window Object
mainWindow.Content = myGrid;
mainWindow.Show ();

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      WindowTitle="StackPanel vs. DockPanel">
  <Grid Width="175" Height="150">
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition />
    </Grid.RowDefinitions>

    <DockPanel Grid.Column="0" Grid.Row="0">
      <Image Source="smiley_stackpanel.png" />
      <Image Source="smiley_stackpanel.png" />
      <Image Source="smiley_stackpanel.png" Stretch="Fill"/>
    </DockPanel>

    <StackPanel Grid.Column="0" Grid.Row="1"  Orientation="Horizontal">
      <Image Source="smiley_stackpanel.png" />
      <Image Source="smiley_stackpanel.png" />
      <Image Source="smiley_stackpanel.png" Stretch="Fill"/>
    </StackPanel>
    </Grid>
</Page>

La diferencia en cuanto al comportamiento de representación se puede ver en esta imagen.

Captura de pantalla: StackPanel frente a Captura de pantalla de DockPanel

En el ejemplo siguiente se muestra cómo utilizar un elemento StackPanel para crear un conjunto de botones colocados verticalmente. Para colocarlos horizontalmente, establezca la propiedad Orientation en Horizontal.

La aplicación compilada produce una nueva IU con esta apariencia.

Elemento StackPanel típico.

WPF también proporciona una variación del elemento StackPanel que "virtualiza" automáticamente el contenido secundario enlazado a datos. En este contexto, el término "virtualizar" se refiere a una técnica por la que se genera un subconjunto de elementos a partir de un número mayor de elementos de datos en función de los elementos que están visibles en pantalla. Generar un gran número de elementos de interfaz de usuario cuando sólo pueden estar en pantalla algunos de ellos en un momento dado, requiere un uso intensivo, tanto de la memoria como del procesador. VirtualizingStackPanel (a través de la funcionalidad proporcionada por VirtualizingPanel) calcula los elementos visibles y trabaja con ItemContainerGenerator desde un control ItemsControl (como ListBox o ListView) para crear elementos únicamente para los elementos visibles.

El elemento VirtualizingStackPanel se establece automáticamente como el host de elementos para controles como ListBox. Al hospedar una colección enlazada a datos, el contenido se virtualiza automáticamente, siempre que el contenido esté dentro de los límites de un elemento ScrollViewer. Esto mejora notablemente el rendimiento cuando se hospedan muchos elementos secundarios.

El marcado siguiente muestra cómo utilizar un elemento VirtualizingStackPanel como un host de elementos. La propiedad adjuntaVirtualizingStackPanel.IsVirtualizing debe estar establecida en true (valor predeterminado) para que se produzca la virtualización.

<StackPanel DataContext="{Binding Source={StaticResource Leagues}}">
    <TextBlock Text="{Binding XPath=@name}" FontFamily="Arial" FontSize="18" Foreground="Black"/>
        <ListBox VirtualizingStackPanel.IsVirtualizing="True" 
                 ItemsSource="{Binding XPath=Team}" 
                 ItemTemplate="{DynamicResource NameDataStyle}"/>      
</StackPanel>

WrapPanel se utiliza para colocar de izquierda a derecha los elementos secundarios en posición secuencial, y traslada el contenido a la línea siguiente cuando alcanza el borde de su contenedor primario. El contenido se puede orientar en sentido horizontal o vertical. WrapPanel resulta útil para los escenarios de interfaz de usuario (UI) de flujo sencillo. También se puede utilizar para aplicar un tamaño uniforme a todos sus elementos secundarios.

En el ejemplo siguiente se muestra cómo crear un elemento WrapPanel para mostrar controles Button que se ajustan cuando llegan al borde de su contenedor.


// Create the application's main window
mainWindow = new System.Windows.Window();
mainWindow.Title = "WrapPanel Sample";


// Instantiate a new WrapPanel and set properties
myWrapPanel = new WrapPanel();
myWrapPanel.Background = System.Windows.Media.Brushes.Azure;
myWrapPanel.Orientation = Orientation.Horizontal;
myWrapPanel.Width = 200;
myWrapPanel.HorizontalAlignment = HorizontalAlignment.Left;
myWrapPanel.VerticalAlignment = VerticalAlignment.Top;

// Define 3 button elements. The last three buttons are sized at width 
// of 75, so the forth button wraps to the next line.
btn1 = new Button();
btn1.Content = "Button 1";
btn1.Width = 200;
btn2 = new Button();
btn2.Content = "Button 2";
btn2.Width = 75;
btn3 = new Button();
btn3.Content = "Button 3";
btn3.Width = 75;
btn4 = new Button();
btn4.Content = "Button 4";
btn4.Width = 75;

// Add the buttons to the parent WrapPanel using the Children.Add method.
myWrapPanel.Children.Add(btn1);
myWrapPanel.Children.Add(btn2);
myWrapPanel.Children.Add(btn3);
myWrapPanel.Children.Add(btn4);

// Add the WrapPanel to the MainWindow as Content
mainWindow.Content = myWrapPanel;
mainWindow.Show();

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowTitle="WrapPanel Sample">
  <Border HorizontalAlignment="Left" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="2">
        <WrapPanel Background="LightBlue" Width="200" Height="100">
            <Button Width="200">Button 1</Button>
            <Button>Button 2</Button>
            <Button>Button 3</Button>
            <Button>Button 4</Button>
        </WrapPanel>
  </Border>    
</Page>

La aplicación compilada produce una nueva IU con esta apariencia.

Elemento WrapPanel típico.

Los elementos Panel pueden anidarse unos dentro de otros para generar los diseños complejos. Esto puede resultar muy útil en situaciones en las que un elemento Panel es ideal para una parte de una IU, pero no puede satisfacer las necesidades de otra parte de la IU.

No existe ningún límite real a la cantidad de anidamiento que puede admitir una aplicación; sin embargo, en general conviene limitar la aplicación para que utilice sólo los paneles que son realmente necesarios para el diseño que se desea. En muchos casos, se puede utilizar un elemento Grid en lugar de paneles anidados debido a su flexibilidad como contenedor de diseño. Esto puede aumentar el rendimiento de una aplicación al dejar fuera del árbol los elementos innecesarios.

En el ejemplo siguiente se muestra cómo crear una IU que hace uso de elementos Panel anidados para lograr un diseño concreto. En este caso concreto, se usa un elemento DockPanel para proporcionar la estructura de la IU y elementos StackPanel anidados, un elemento Grid y un elemento Canvas para colocar con precisión los elementos secundarios dentro del elemento DockPanel primario.

La aplicación compilada produce una nueva IU con esta apariencia.

IU que aprovecha los paneles anidados.

Aunque WPF proporciona una serie de controles de diseño flexibles, también se pueden lograr comportamientos de diseño personalizados invalidando los métodos ArrangeOverride y MeasureOverride. Es posible ajustar de forma personalizada el tamaño y la posición definiendo nuevos comportamientos de posición mediante estos métodos de invalidación.

De igual forma, los comportamientos de diseño personalizados basados en clases derivadas (como Canvas o Grid) se pueden definir invalidando sus métodos ArrangeOverride y MeasureOverride.

En el marcado siguiente se muestra cómo crear un elemento Panel personalizado. Este nuevo elemento Panel, definido como PlotPanel, admite la posición de elementos secundarios a través del uso de coordenadas x e y incluidas en el código. En este ejemplo, se coloca un elemento Rectangle (no se muestra) en las coordenadas 50 (x) y 50 (y).

public class PlotPanel : Panel
{
    // Default public constructor
    public PlotPanel()
        : base()
    {
    }

    // Override the default Measure method of Panel
    protected override Size MeasureOverride(Size availableSize)
    {
        Size panelDesiredSize = new Size();

        // In our example, we just have one child. 
        // Report that our panel requires just the size of its only child.
        foreach (UIElement child in InternalChildren)
        {
            child.Measure(availableSize);
            panelDesiredSize = child.DesiredSize;
        }

        return panelDesiredSize ;
    }
    protected override Size ArrangeOverride(Size finalSize)
    {
        foreach (UIElement child in InternalChildren)
        {
            double x = 50;
            double y = 50;

            child.Arrange(new Rect(new Point(x, y), child.DesiredSize));
        }
        return finalSize; // Returns the final Arranged size
    }
}

Para obtener una implementación de un panel personalizado más complejo, vea Create a Custom Content-Wrapping Panel Sample.

WPF admite diversas características que facilitan la creación de una IU localizable.

Todos los elementos Panel admiten de forma nativa la propiedad FlowDirection, que se puede utilizar para alterar dinámicamente el flujo del contenido basándose en la configuración regional o de idioma del usuario. Para obtener más información, vea FlowDirection.

La propiedad SizeToContent proporciona un mecanismo que permite a los programadores de aplicaciones anticiparse a las necesidades de localización de la IU. Con el valor WidthAndHeight de esta propiedad, un elemento Window primario siempre ajusta su tamaño dinámicamente de acuerdo con el contenido y no está sujeto a restricciones artificiales en cuanto al alto o al ancho.

DockPanel, Grid y StackPanel son buenas opciones para crear una IU localizable. Sin embargo, Canvas no es adecuada, porque sitúa el contenido de forma absoluta, lo que hace que sea difícil su localización.

Para obtener información adicional sobre cómo crear aplicaciones de WPF con user interfaces (UIs) localizables, vea Información general sobre el uso del diseño automático.

Mostrar: