WPF: ComboBox без кнопки выпадающего списка
Я хочу ComboBox, который не имеет раскрывающейся кнопки, но все еще может быть открыт, когда я нажимаю на текст в combobox. Возможно ли это с помощью WPF combobox?
2 ответов
это возможно, но вам нужно будет перепечатать его, чтобы достичь совершенства. Вы можете получить большую часть пути, переопределив системный параметр следующим образом:
<ComboBox xmlns:sys="clr-namespace:System;assembly=mscorlib">
<ComboBox.Resources>
<sys:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">0</sys:Double>
</ComboBox.Resources>
<ComboBoxItem>One</ComboBoxItem>
<ComboBoxItem>Two</ComboBoxItem>
<ComboBoxItem>Three</ComboBoxItem>
</ComboBox>
однако он не идеален, потому что прямоугольник фокуса по-прежнему предполагает наличие раскрывающейся кнопки.
все элементы управления WPF "выглядят", поэтому вы можете полностью переопределить их внешний вид. Однако это не просто и тем более для ComboBox. ComboBox использует один из двух шаблонов, в зависимости от того, доступен ли он для редактирования. Не редактируемая версия использует ToggleButton для внешнего вида элемента управления, поэтому вы можете просто удалить чертеж стрелки (см. ниже). Редактируемая версия использует текстовое поле и ToggleButton, и если у вас нет ToggleButton, он не открывается. Итак, вот шаблон без Выключатель; это до вас, чтобы добавить код для обработки нажатий на редактируемый шаблон. (Или, если вам не нужно редактировать, вы можете просто принудить IsEditable к false и покончить с этим.)
предостережение: это шаблон Aero и использует Aero chrome, поэтому он не будет отображаться в других темах. Для этого вам нужно будет вытащить шаблоны для каждой темы и внести соответствующие изменения или удалить тему chrome и нарисовать свои собственные границы.
добавить определение пространства имен и добавление ссылки на PresentationFramework.Aero:
xmlns:t="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
затем добавьте в окно/ресурсы управления следующее:
<Style x:Key="ComboBoxFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Stroke="Black" StrokeDashArray="1 2" StrokeThickness="1" Margin="4,4,21,4" SnapsToDevicePixels="true"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#F3F3F3" Offset="0"/>
<GradientStop Color="#EBEBEB" Offset="0.5"/>
<GradientStop Color="#DDDDDD" Offset="0.5"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
<Geometry x:Key="DownArrowGeometry">M 0 0 L 3.5 4 L 7 0 Z</Geometry>
<Style x:Key="ComboBoxReadonlyToggleButton" TargetType="{x:Type ToggleButton}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="ClickMode" Value="Press"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<t:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}">
<!-- Remove ToggleButton appearance; we still need the ToggleButton because it displays the content.
<Grid HorizontalAlignment="Right" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
<Path x:Name="Arrow" Fill="Black" HorizontalAlignment="Center" Margin="3,1,0,0" VerticalAlignment="Center" Data="{StaticResource DownArrowGeometry}"/>
</Grid>
-->
</t:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
</Trigger>
<!-- Remove ToggleButton appearance trigger
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Fill" TargetName="Arrow" Value="#AFAFAF"/>
</Trigger>
-->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">
<GradientStop Color="#ABADB3" Offset="0.05"/>
<GradientStop Color="#E2E3EA" Offset="0.07"/>
<GradientStop Color="#E3E9EF" Offset="1"/>
</LinearGradientBrush>
<Style x:Key="ComboBoxEditableTextBox" TargetType="{x:Type TextBox}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer x:Name="PART_ContentHost" Background="Transparent" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="ClickMode" Value="Press"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<t:ButtonChrome x:Name="Chrome" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RoundCorners="false">
<Path x:Name="Arrow" Fill="Black" HorizontalAlignment="Center" Margin="0,1,0,0" VerticalAlignment="Center" Data="{StaticResource DownArrowGeometry}"/>
</t:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Fill" TargetName="Arrow" Value="#AFAFAF"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="ComboBoxEditableTemplate" TargetType="{x:Type ComboBox}">
<Grid x:Name="Placement" SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Popup x:Name="PART_Popup" AllowsTransparency="true" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Grid.ColumnSpan="2">
<t:SystemDropShadowChrome x:Name="Shdw" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=Placement}" Color="Transparent">
<Border x:Name="DropDownBorder" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1">
<ScrollViewer>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.DirectionalNavigation="Contained"/>
</ScrollViewer>
</Border>
</t:SystemDropShadowChrome>
</Popup>
<t:ListBoxChrome x:Name="Border" Grid.ColumnSpan="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}"/>
<TextBox x:Name="PART_EditableTextBox" Margin="{TemplateBinding Padding}" Style="{StaticResource ComboBoxEditableTextBox}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}"/>
<!-- Remove the ToggleButton button; now you make the textbox clickable....
<ToggleButton Style="{StaticResource ComboBoxToggleButton}" Grid.Column="1" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
-->
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="true">
<Setter Property="Foreground" Value="Black"/>
</Trigger>
<Trigger Property="IsDropDownOpen" Value="true">
<Setter Property="RenderFocused" TargetName="Border" Value="true"/>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="Height" TargetName="DropDownBorder" Value="95"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
<Setter Property="Background" Value="#FFF4F4F4"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
<Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
<Setter Property="Color" TargetName="Shdw" Value="#71000000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="ButtonlessComboBoxStyle" TargetType="{x:Type ComboBox}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ComboBoxFocusVisual}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Padding" Value="4,3"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid x:Name="MainGrid" SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
</Grid.ColumnDefinitions>
<Popup x:Name="PART_Popup" Margin="1" AllowsTransparency="true" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Grid.ColumnSpan="2">
<t:SystemDropShadowChrome x:Name="Shdw" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}" Color="Transparent">
<Border x:Name="DropDownBorder" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1">
<ScrollViewer CanContentScroll="true">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.DirectionalNavigation="Contained"/>
</ScrollViewer>
</Border>
</t:SystemDropShadowChrome>
</Popup>
<ToggleButton Style="{StaticResource ComboBoxReadonlyToggleButton}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" IsHitTestVisible="false" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
<Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
<Setter Property="Color" TargetName="Shdw" Value="#71000000"/>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="Height" TargetName="DropDownBorder" Value="95"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
<Setter Property="Background" Value="#FFF4F4F4"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEditable" Value="true">
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="Template" Value="{StaticResource ComboBoxEditableTemplate}"/>
</Trigger>
</Style.Triggers>
</Style>
затем использовать:
<ComboBox HorizontalAlignment="Left" Width="120" Style="{DynamicResource ButtonlessComboBoxStyle}">
<ComboBox.Items>
<ComboBoxItem>One</ComboBoxItem>
<ComboBoxItem>Two</ComboBoxItem>
<ComboBoxItem>Three</ComboBoxItem>
</ComboBox.Items>
</ComboBox>
<ComboBox HorizontalAlignment="Left" Width="120" IsEditable="True" Style="{DynamicResource ButtonlessComboBoxStyle}">
<ComboBox.Items>
<ComboBoxItem>One</ComboBoxItem>
<ComboBoxItem>Two</ComboBoxItem>
<ComboBoxItem>Three</ComboBoxItem>
</ComboBox.Items>
</ComboBox>
Примечание: стили ссылаются как DynamicResource
потому что они полагаются на тему chrome так нужно реагировать на изменения в визуальном стиле ОС. Если вы удалите chrome и используете границы WPF, вы должны ссылаться на них как StaticResource
для исполнения.