阻止组合框根据所选项目展开

本文关键字:选项 项目 组合 | 更新日期: 2023-09-27 18:25:56

我想阻止组合框根据所选项目的大小调整大小。考虑这个简化的例子:

<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>

当您在第二个组合框中选择第一个项目时,该组合框将展开,以使所选项目的整个内容适合,从而在左侧中隐藏组合框

我想实现三件事:

  • 使用滚动查看器,使控件符合其最小大小
  • 如果窗口很大,我希望第二个组合框适合剩余的大小
  • 如果我在第二个组合框中选择了一个很长的项目,我希望它保持原来的大小,并且根据所选项目的内容进行调整

有可能吗?

阻止组合框根据所选项目展开

编辑:

我又看了一遍这个问题,找到了比以前提出的简单得多的解决方案。其思想是覆盖ComboBox类的MeasureOverride函数,并提供有限的可用空间,其中width等于ComboBox的MinWidth属性。为了做到这一点,我们创建了ComboBox派生类:

public class MyComboBox
        : ComboBox
{
    protected override Size MeasureOverride(Size constraint)
    {
        return base.MeasureOverride(new Size(MinWidth, constraint.Height));
    }
}

然后我们在控制中使用它来代替组合框,HorizontalContentAlignment设置为Stretch:

<local:MyComboBox Grid.Column="1" Margin="5" MinWidth="110"
                                  HorizontalContentAlignment="Stretch">
    <ComboBoxItem Content="Very loooooooooooooooooooooooooooooooooooooooong text"/>
    <ComboBoxItem Content="Normal text"/>
</local:MyComboBox>


以前提出的过于复杂的解决方案:

您可以将第二个组合框的MaxWidth属性绑定到剩余的空间(您可以计算它):

<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>

我正在从滚动查看器的ActualWidth减去第一个组合框的ActualWidth、它的边距和第二个组合框。为了减少要减去的元素,可以在ComboBox1周围放置一个边框。然后,您将减去border的ActualWidth,而不是ComboBox1属性。

此处使用的转换器:

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();
    }
}

我在ScrollViewer中的ComboBox也遇到了同样的问题。我不想要水平滚动,只想要垂直滚动。但是组合框不断调整大小以适应所选项目。我使用了对齐器答案,但将MinWidth替换为ActualWidth,这样可以防止组合框调整大小,但所选项目将始终使用可用空间。

public class FixedWidthComboBox : ComboBox
{
    protected override Size MeasureOverride(Size constraint)
    {
        return base.MeasureOverride(new Size(ActualWidth, constraint.Height));
    }
}