【问题标题】:WPF ComboBox without drop-down button没有下拉按钮的WPF ComboBox
【发布时间】:2010-11-25 06:59:51
【问题描述】:

我想要一个ComboBox,它没有下拉按钮,但当我单击ComboBox 中的文本时仍然可以打开它。 WPF ComboBox 可以做到这一点吗?

【问题讨论】:

    标签: wpf user-interface xaml controls combobox


    【解决方案1】:

    也许这可以帮助你

    Dispatcher.BeginInvoke(new Action(() =>
                {
                    ToggleButton dropDownButton = GetFirstChildOfType<ToggleButton>(cboMedicos);
                    if (dropDownButton != null)
                    {
                        dropDownButton.IsEnabled = false;
                    }
    
                }), System.Windows.Threading.DispatcherPriority.Render);
    
    
    
    
            public static T GetFirstChildOfType<T>(DependencyObject dependencyObject) where T : DependencyObject
            {
                if (dependencyObject == null)
                {
                    return null;
                }
    
                for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
                {
                    var child = VisualTreeHelper.GetChild(dependencyObject, i);
    
                    var result = (child as T) ?? GetFirstChildOfType<T>(child);
    
                    if (result != null)
                    {
                        return result;
                    }
                }
    
                return null;
            }
    

    【讨论】:

      【解决方案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>
      

      但是,它并不完美,因为焦点矩形仍然假定存在一个下拉按钮。

      【讨论】:

      • 我必须添加 xmlns:sys="clr-namespace:System;assembly=mscorlib",以使其工作:)
      • 您认为可以将它与数据绑定一起使用吗?
      【解决方案3】:

      所有 WPF 控件都是“无外观”的,因此您可以完全重新定义它们的外观。然而,对于 ComboBox 来说,这并不简单,甚至更不简单。 ComboBox 使用两个模板之一,具体取决于它是否可编辑。不可编辑的版本使用 ToggleButton 作为控件外观,因此您可以删除箭头图(见下文)。可编辑版本使用 TextBox 和 ToggleButton,如果没有 ToggleButton,它不会打开。所以这是一个没有 ToggleButton 的模板;您可以添加代码来处理对可编辑模板的点击。 (或者如果你不需要编辑,你可以将 IsEditable 强制为 false 并完成它。)

      警告:这是 Aero 模板并使用 Aero 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 以提高性能。

      【讨论】:

      • 感谢您的代码和良好的解释。太糟糕了,它只适用于航空:(
      • 您总是可以参考不同的 MS 主题,例如 Luna,而不是使用 Aero。我们在主题中使用 Luna,因为我们的办公电脑都运行 XP。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      • 1970-01-01
      • 2013-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多