Eu sei como fazer isso em código, mas isso pode ser feito em 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;
}
}
}
Respostas:
Isso não pode ser em XAML sem:
O motivo para isso é que os ComboBox ControlTemplates padrão que encontrei (Aero, Luna, etc.) aninham o ItemsPresenter em um Popup. Isso significa que o layout desses itens é adiado até que eles se tornem realmente visíveis.
Uma maneira fácil de testar isso é modificar o ControlTemplate padrão para vincular o MinWidth do contêiner mais externo (é um Grid para Aero e Luna) ao ActualWidth de PART_Popup. Você poderá fazer com que o ComboBox sincronize automaticamente sua largura ao clicar no botão de soltar, mas não antes.
Portanto, a menos que você possa forçar uma operação Medir no sistema de layout (o que pode ser feito adicionando um segundo controle), não acho que isso possa ser feito.
Como sempre, estou aberto a uma solução curta e elegante - mas, neste caso, hacks code-behind ou dual-control / ControlTemplate são as únicas soluções que vi.
fonte
Você não pode fazer isso diretamente no Xaml, mas pode usar este comportamento anexado. (A largura ficará visível no Designer)
The Attached Behavior ComboBoxWidthFromItemsProperty
O que ele faz é chamar um método de extensão para ComboBox chamado SetWidthFromItems que (invisivelmente) se expande e se retrai e então calcula a largura com base nos ComboBoxItems gerados. (IExpandCollapseProvider requer uma referência a UIAutomationProvider.dll)
Em seguida, o método de extensão SetWidthFromItems
Este método de extensão também fornece a capacidade de chamar
no code behind (por exemplo, no evento ComboBox.Loaded)
fonte
SetWidthFromItems
assíncrono my usando uma action / delegate e um BeginInvoke com uma prioridade Idle (como feito no evento Loaded). Dessa forma, nenhuma medida será feita enquanto a bomba de mensagem não estiver vazia e, portanto, nenhuma intercalação de mensagem ocorrerádouble comboBoxWidth = 19;
em seu código está relacionado aSystemParameters.VerticalScrollBarWidth
?Sim, este é um pouco desagradável.
O que fiz no passado foi adicionar ao ControlTemplate uma caixa de listagem oculta (com seu painel de contêiner de itens definido como uma grade) mostrando cada item ao mesmo tempo, mas com sua visibilidade definida como oculta.
Eu ficaria satisfeito em saber de ideias melhores que não dependem do horrível code-behind ou de sua visualização ter que entender que ele precisa usar um controle diferente para fornecer a largura para suportar os visuais (eca!).
fonte
Com base nas outras respostas acima, aqui está minha versão:
HorizontalAlignment = "Left" interrompe os controles usando a largura total do controle que o contém. Height = "0" oculta o controle de itens.
Margin = "15,0" permite cromo adicional em torno de itens da caixa de combinação (não é agnóstico de cromo, infelizmente).
fonte
Acabei com uma solução "boa o suficiente" para esse problema: fazer com que a caixa de combinação nunca diminua abaixo do maior tamanho que ela continha, semelhante ao antigo WinForms AutoSizeMode = GrowOnly.
A maneira como fiz isso foi com um conversor de valor personalizado:
Em seguida, configuro a caixa de combinação em XAML assim:
Observe que, com isso, você precisa de uma instância separada do GrowConverter para cada caixa de combinação, a menos, é claro, que você queira que um conjunto deles seja dimensionado juntos, semelhante ao recurso SharedSizeScope do Grid.
fonte
Seguindo a resposta de Maleak: Gostei tanto dessa implementação que escrevi um Behavior real para ela. Obviamente, você precisará do Blend SDK para que possa fazer referência a System.Windows.Interactivity.
XAML:
Código:
fonte
provider.Expand()
joga umElementNotEnabledException
. Quando o ComboBox não está habilitado, devido a um dos pais estar desabilitado, então não é nem mesmo possível habilitar temporariamente o ComboBox até que a medição seja concluída.Coloque uma caixa de listagem com o mesmo conteúdo atrás da caixa de depósito. Em seguida, reforce a altura correta com alguma amarração como esta:
fonte
No meu caso, uma maneira muito mais simples parecia funcionar, apenas usei um stackPanel extra para embrulhar a caixa de combinação.
(trabalhou no visual studio 2008)
fonte
Uma solução alternativa para a primeira resposta é Medir o próprio Popup em vez de medir todos os itens. Oferecendo uma
SetWidthFromItems()
implementação um pouco mais simples :funciona em aparelhos com deficiência
ComboBox
também.fonte
Eu estava procurando a resposta, quando me deparei com o
UpdateLayout()
método que todo mundoUIElement
tem.É muito simples agora, felizmente!
Basta ligar
ComboBox1.Updatelayout();
depois de definir ou modificar oItemSource
.fonte
Abordagem de Alun Harford, na prática:
fonte
Isso mantém a largura até o elemento mais largo, mas somente após abrir a caixa de combinação uma vez.
fonte