Prevent ComboBox to expand acording to selected item
c#, layout, wpf
Solution
Edit:
I looked again at the problem and found out much simpler solution than previously proposed. The idea is to override MeasureOverride function of the ComboBox class and provide limited space that is available, where width is equal to the MinWidth property of the ComboBox. In order to do that we create ComboBox derived class:
public class MyComboBox
: ComboBox
{
protected override Size MeasureOverride(Size constraint)
{
return base.MeasureOverride(new Size(MinWidth, constraint.Height));
}
}
and then we use it in our control in place of ComboBox with HorizontalContentAlignment set to Stretch:
<local:MyComboBox Grid.Column="1" Margin="5" MinWidth="110"
HorizontalContentAlignment="Stretch">
<ComboBoxItem Content="Very loooooooooooooooooooooooooooooooooooooooong text"/>
<ComboBoxItem Content="Normal text"/>
</local:MyComboBox>
Previously proposed, too complex solution:
You can bind the MaxWidth property of the second ComboBox to the space which is left (you can calculate it):
<Window x:Class="Example.MainWindow"
xmlns:local="clr-namespace:Example"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="150" Width="300">
<Window.Resources>
<local:SubstractConverter x:Key="SubstractConverter"/>
</Window.Resources>
<GroupBox Header="Group Header" Margin="5">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
x:Name="ScrollViewer1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ComboBox MinWidth="100" Grid.Column="0" Margin="5" MaxWidth="150"
x:Name="ComboBox1"/>
<ComboBox Grid.Column="1" Margin="5" MinWidth="110">
<ComboBox.MaxWidth>
<MultiBinding Converter="{StaticResource SubstractConverter}">
<Binding ElementName="ScrollViewer1" Path="ActualWidth"/>
<Binding ElementName="ComboBox1" Path="ActualWidth"/>
<Binding ElementName="ComboBox1" Path="Margin.Left"/>
<Binding ElementName="ComboBox1" Path="Margin.Right"/>
<Binding Path="Margin.Left" RelativeSource="{RelativeSource Self}"/>
<Binding Path="Margin.Right" RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</ComboBox.MaxWidth>
<ComboBoxItem Content="Very loooooooooooooooooooooooooooooooooooooooong text"/>
<ComboBoxItem Content="Normal text"/>
</ComboBox>
</Grid>
</ScrollViewer>
</GroupBox>
</Window>
I'm substracting ActualWidth of the first combobox, its margins and margins of the second combobox from the ActualWidth of the scrollviewer. In order to have less elements to substract, you can put a border around ComboBox1. You will then substract border's ActualWidth instead of ComboBox1 properties.
Converter which is used here:
public class SubstractConverter
: IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values != null && values.Any())
{
var result = System.Convert.ToDouble(values.First());
var toSubstract = values.Skip(1);
foreach (var number in toSubstract)
{
result -= System.Convert.ToDouble(number);
}
return result;
}
return 0d;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Problem
I want to prevent a ComboBox to resize acording to the size of the selected item. Consider this simplified example: ``` <Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="150" Width="300"> <GroupBox Header="Group Header" Margin="5"> <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <ComboBox MinWidth="100" Grid.Column="0" Margin="5" MaxWidth="150"/> <ComboBox Grid.Column="1" Margin="5" MinWidth="110"> <ComboBoxItem Content="Very loooooooooooooooooooooooooooooooooooooooong text"/> <ComboBoxItem Content="Normal text"/> </ComboBox> </Grid> </ScrollViewer> </GroupBox> </Window> ``` When you select the first item in the second ComboBox, that ComboBox is expanded so the whole content of the selected item fits, hiding the ComboBox from the left I would like to achieve three things: - Have the scrollviewer so the controls fit in their minimum size - If the Window is very large, I want the second ComboBox to fit the remaining size - If I select a very long item in the second ComboBox, I want it to preserve the size it had and not adjust to the contents of the selected item Is it possible?