Sé cómo hacerlo en código, pero ¿se puede hacer en XAML?
Window1.xaml:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<ComboBox Name="ComboBox1" HorizontalAlignment="Left" VerticalAlignment="Top">
<ComboBoxItem>ComboBoxItem1</ComboBoxItem>
<ComboBoxItem>ComboBoxItem2</ComboBoxItem>
</ComboBox>
</Grid>
</Window>
Window1.xaml.cs:
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
double width = 0;
foreach (ComboBoxItem item in ComboBox1.Items)
{
item.Measure(new Size(
double.PositiveInfinity, double.PositiveInfinity));
if (item.DesiredSize.Width > width)
width = item.DesiredSize.Width;
}
ComboBox1.Measure(new Size(
double.PositiveInfinity, double.PositiveInfinity));
ComboBox1.Width = ComboBox1.DesiredSize.Width + width;
}
}
}
Respuestas:
Esto no puede estar en XAML sin:
La razón de esto es que las plantillas de control de ComboBox predeterminadas con las que me he encontrado (Aero, Luna, etc.) anidan todos los ItemsPresenter en un Popup. Esto significa que el diseño de estos elementos se aplaza hasta que se hagan visibles.
Una manera fácil de probar esto es modificar la ControlTemplate predeterminada para vincular el MinWidth del contenedor más externo (es una Grid para Aero y Luna) al ActualWidth de PART_Popup. Podrá hacer que ComboBox sincronice automáticamente su ancho cuando haga clic en el botón para soltar, pero no antes.
Entonces, a menos que pueda forzar una operación de Medición en el sistema de diseño (lo que puede hacer agregando un segundo control), no creo que se pueda hacer.
Como siempre, estoy abierto a una solución corta y elegante, pero en este caso, las únicas soluciones que he visto son un código subyacente o un control dual / ControlTemplate.
fuente
No puede hacerlo directamente en Xaml, pero puede usar este comportamiento adjunto. (El ancho será visible en el diseñador)
ComboBoxWidthFromItemsProperty de comportamiento adjunto
Lo que hace es que llama a un método de extensión para ComboBox llamado SetWidthFromItems que (de manera invisible) se expande y colapsa y luego calcula el Ancho en función de los ComboBoxItems generados. (IExpandCollapseProvider requiere una referencia a UIAutomationProvider.dll)
Luego, método de extensión SetWidthFromItems
Este método de extensión también proporciona la capacidad de llamar
en el código subyacente (por ejemplo, en el evento ComboBox.Loaded)
fuente
SetWidthFromItems
asincrónico usando una acción / delegado y un BeginInvoke con una prioridad de inactividad (como se hizo en el evento Loaded). De esta manera, no se tomará ninguna medida mientras la bomba de mensajes no esté vacía y, por lo tanto, no se producirá ningún intercalado de mensajesdouble comboBoxWidth = 19;
en su códigoSystemParameters.VerticalScrollBarWidth
?Sí, este es un poco desagradable.
Lo que he hecho en el pasado es agregar a ControlTemplate un cuadro de lista oculto (con su panel de contenido de elementos configurado en una cuadrícula) que muestra todos los elementos al mismo tiempo pero con su visibilidad configurada como oculta.
Me complacería escuchar alguna idea mejor que no se base en un código subyacente horrible o que su vista tenga que entender que necesita usar un control diferente para proporcionar el ancho para soportar las imágenes (¡puaj!).
fuente
Según las otras respuestas anteriores, aquí está mi versión:
HorizontalAlignment = "Left" detiene los controles usando el ancho completo del control contenedor. Height = "0" oculta el control de los elementos.
Margin = "15,0" permite cromo adicional alrededor de los elementos del cuadro combinado (me temo que no es independiente del cromo).
fuente
Terminé con una solución "suficientemente buena" para este problema que era hacer que el cuadro combinado nunca se redujera por debajo del tamaño más grande que tenía, similar al antiguo WinForms AutoSizeMode = GrowOnly.
La forma en que hice esto fue con un convertidor de valor personalizado:
Luego configuro el cuadro combinado en XAML así:
Tenga en cuenta que con esto necesita una instancia separada de GrowConverter para cada cuadro combinado, a menos que, por supuesto, desee un conjunto de ellos para medir juntos, similar a la función SharedSizeScope de Grid.
fuente
Un seguimiento de la respuesta de Maleak: me gustó tanto esa implementación que escribí un comportamiento real para ella. Obviamente, necesitará el SDK de Blend para poder hacer referencia a System.Windows.Interactivity.
XAML:
Código:
fuente
provider.Expand()
lanza unElementNotEnabledException
. Cuando el ComboBox no está habilitado, debido a que un padre está deshabilitado, entonces ni siquiera es posible habilitar temporalmente el ComboBox hasta que la medición haya finalizado.Coloque un cuadro de lista que contenga el mismo contenido detrás del cuadro desplegable. Luego aplique la altura correcta con un enlace como este:
fuente
En mi caso, una forma mucho más simple pareció funcionar, solo usé un stackPanel adicional para envolver el cuadro combinado.
(trabajó en visual studio 2008)
fuente
Una solución alternativa a la respuesta principal es medir la ventana emergente en sí en lugar de medir todos los elementos. Dando una
SetWidthFromItems()
implementación un poco más simple :también funciona en discapacitados
ComboBox
.fuente
Yo mismo buscaba la respuesta cuando encontré el
UpdateLayout()
método que todosUIElement
tienen.¡Es muy simple ahora, afortunadamente!
Simplemente llame
ComboBox1.Updatelayout();
después de configurar o modificar elItemSource
.fuente
El enfoque de Alun Harford, en la práctica:
fuente
Esto mantiene el ancho al elemento más ancho pero solo después de abrir el cuadro combinado una vez.
fuente