.net - template - listbox wpf
Controles de estiramiento para llenar ItemsControl (3)
Pude basarme en la respuesta de Nir para cumplir con mi criterio opcional, que permite el estiramiento administrado por WPF con múltiples filas.
Primero debe poder alterar las propiedades de la plantilla UniformGrid . Para hacer eso, necesitas almacenar una referencia a él. Existen múltiples métodos para lograr esto . Elegí manejar el evento Loaded para UniformGrid y almacenar una referencia en ese momento.
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1" Loaded="UniformGrid_Loaded" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Y en el código detrás:
UniformGrid uniformgridButtons;
private void UniformGrid_Loaded(object sender, RoutedEventArgs e)
{
uniformgridButtons = sender as UniformGrid;
}
Luego, maneje el evento SizeChanged y ajuste el parámetro de filas de acuerdo con los criterios que desee.
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
if ((uniformgridButtons != null) && (this.Width > 0))
{
// Set row count according to your requirements
uniformgridButtons.Rows = (int)(1 + ((this.MinWidth * iButtonCount) / this.Width));
}
}
Esto permite que WPF administre el estiramiento como en la respuesta de Nir, pero le permite ajustar explícitamente el número de filas. El código anterior da este resultado:
(Muestra animada here )
Actualización 28/08/2009:
Estaba ajustando mi aplicación de aprendizaje para que ItemsControl
estuviera en un DataTemplate
en un ResourceDictionary
separado. Sin embargo, eventos como Loaded
no se pueden manejar en un archivo ResourceDictionary
XAML externo porque no tiene código subyacente (generalmente). Por lo tanto, necesitaba UniformGrid
la memoria caché la referencia a UniformGrid
usando una técnica diferente.
En su lugar , FindItemsPanel
método FindItemsPanel
Alan Haigh (10ª respuesta) . Primero, reemplacé el ItemsControl
por:
<ContentPresenter x:Name="contentpresenterButtons" Content="{Binding obscolButtons}" />
Luego, en mi ResourceDictionary
, puse el ItemsControl
en DataTemplate
:
<DataTemplate DataType="{x:Type local:Buttons}">
<ItemsControl ...
</DataTemplate>
Finalmente, UniformGrid
la referencia al UniformGrid
plantilla así:
private void Window_Loaded(object sender, RoutedEventArgs e) {
uniformgridButtons = FindItemsPanel<UniformGrid>(contentpresenterButtons);
// Also call the code in Window_SizeChanged which I put in another method
}
Esto funciona igual que mi solución anterior pero sin requerir un controlador de eventos en ResourceDictionary
.
Estoy intentando escribir un proyecto de aprendizaje de WPF simple que crea un conjunto de botones dentro de una ventana principal redimensionable. Debe haber un Button
por entrada en una colección, y el contenido de esa colección puede variar durante el tiempo de ejecución. Quiero que los botones llenen toda la ventana (por ejemplo, 1 botón @ 100% de ancho, 2 botones @ 50% de ancho, 3 botones a 33% de ancho, etc., todos al 100% de altura). Una versión simplificada de lo que he escrito hasta ahora es:
<ItemsControl x:Name="itemscontrolButtons" ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Tag="{Binding}">
<TextBlock Text="{Binding}" />
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
...
List<string> listButtonTexts = new List<string>() { "Button1", "Button2" };
...
itemscontrolButtons.DataContext = listButtonTexts;
Esto resulta en esto:
No he podido hacer que los botones se estiren para que se ajusten al ancho y mis intentos de usar una Grid
lugar de StackPanel
fueron infructuosos.
Luego, como una mejora opcional, agradecería sugerencias sobre cómo ajustarlo de manera que si hay tantos botones que no pueden caber correctamente en una línea o si son más angostos que un umbral, se envolverá en una nueva línea (reduciendo a la mitad la alturas de los botones si van de 1 a 2 filas).
Me gustaría enfatizar que me gustaría saber cómo hacer esto de la manera WPF . Me doy cuenta de que puedo consumir mensajes de cambio de tamaño de ventana y cambiar el tamaño de los controles de forma explícita, y así es como lo hubiera hecho con MFC o WinForms, pero por lo que he leído, no es así como deberían hacerse con WPF.
Reemplace el panel del control del artículo con un UniformGrid, esto ajustará el tamaño de todos los niños para que todo encaje exactamente:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<!-- width must be explicitly set for this example -->
<StackPanel
Name="MyStack"
Orientation="Horizontal"
Width="250"
Load="Window_Loaded">
<Button/>
<Button/>
<Button/>
</StackPanel>
public void Window_Loaded(object sender, RoutedEventArgs e)
{
UIElementCollection elements = MyStack.Children;
int count = elements.Count;
foreach (UIElement element in elements)
{
if (element is Button)
((Button)element).Width = MyStack.Width / count;
}
}