【问题标题】:WPF ComboBox with custom style, cannot expand DropDown after clicking inside of ComboBox具有自定义样式的WPF ComboBox,单击ComboBox内部后无法展开DropDown
【发布时间】:2011-09-25 03:29:30
【问题描述】:

我为ComboBox 添加了以下样式,这是我一年前在 WPFToolkit 中偶然发现的。

它缺少一个基本功能,也就是说,如果我在ComboBoxTextBox 内单击,我希望下拉菜单像往常一样展开。在此模板中,下拉菜单只能通过直接单击ComboBoxToggleButton 来打开。

我不知道在模板样式中要寻找什么,你能指导我吗?

模板样式:

<ControlTemplate x:Key="ComboBoxToggleButton"
                 TargetType="{x:Type ToggleButton}">
    <ControlTemplate.Resources>
        <Storyboard x:Key="HoverOn">
            <DoubleAnimation Duration="00:00:00.1000000"
                             Storyboard.TargetName="rectangleOver"
                             Storyboard.TargetProperty="Opacity"
                             To="0.8" />
            <ColorAnimation Duration="00:00:00.1000000"
                            Storyboard.TargetName="Background"
                            Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                            To="#FFFFFFFF" />
        </Storyboard>
        <Storyboard x:Key="HoverOff">
            <DoubleAnimation Duration="00:00:00.4000000"
                             Storyboard.TargetName="rectangleOver"
                             Storyboard.TargetProperty="Opacity"
                             To="0" />
            <ColorAnimation Duration="00:00:00.4000000"
                            Storyboard.TargetName="Background"
                            Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                            To="#FFffffff" />
        </Storyboard>
        <Storyboard x:Key="PressedOn">
            <DoubleAnimation Duration="00:00:00.1000000"
                             Storyboard.TargetName="rectanglePress"
                             Storyboard.TargetProperty="Opacity"
                             To="0.8" />
            <ColorAnimation Duration="00:00:00.1000000"
                            Storyboard.TargetName="Background"
                            Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                            To="#FFFFFFFF" />
        </Storyboard>
        <Storyboard x:Key="PressedOff">
            <DoubleAnimation Duration="00:00:00.4000000"
                             Storyboard.TargetName="rectanglePress"
                             Storyboard.TargetProperty="Opacity"
                             To="0" />
            <ColorAnimation Duration="00:00:00.4000000"
                            Storyboard.TargetName="Background"
                            Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                            To="#FFffffff" />
        </Storyboard>
        <Storyboard x:Key="CheckedOn">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="BackgroundChecked"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
                                      Value="1" />
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="CheckedOff">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="BackgroundChecked"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00.3000000"
                                      Value="0" />
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </ControlTemplate.Resources>
    <Grid x:Name="grid">
        <Rectangle x:Name="Background"
                   Fill="#ffffff"
                   Stroke="#ffc6c6c6"
                   RadiusX="3"
                   RadiusY="3"
                   IsHitTestVisible="false" />
        <Rectangle x:Name="BackgroundChecked"
                   Margin="1"
                   IsHitTestVisible="false"
                   Opacity="0">
            <Rectangle.Fill>
                <SolidColorBrush Color="{DynamicResource WhiteColor}" />
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle x:Name="rectangleOver"
                   Width="15"
                   Stroke="#FFE8E8E8"
                   HorizontalAlignment="Right"
                   Opacity="0"
                   Fill="{DynamicResource MouseOverBrush}" />
        <Rectangle x:Name="rectanglePress"
                   Width="15"
                   Stroke="#FC9E9D9B"
                   HorizontalAlignment="Right"
                   Opacity="0"
                   Fill="{DynamicResource PressedBrush}" />
        <Rectangle x:Name="DisabledVisualElement"
                   Margin="1"
                   Fill="{DynamicResource DisabledBackgroundBrush}"
                   IsHitTestVisible="false"
                   Visibility="Collapsed" />
        <Path x:Name="BtnArrow"
              Margin="0,0,4,0"
              Width="6"
              Fill="{DynamicResource GlyphBrush}"
              Stretch="Uniform"
              HorizontalAlignment="Right"
              Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z " />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsPressed"
                 Value="True">
            <Trigger.ExitActions>
                <BeginStoryboard Storyboard="{StaticResource PressedOff}"
                                 x:Name="PressedOff_BeginStoryboard" />
            </Trigger.ExitActions>
            <Trigger.EnterActions>
                <BeginStoryboard Storyboard="{StaticResource PressedOn}"
                                 x:Name="PressedOn_BeginStoryboard" />
            </Trigger.EnterActions>
        </Trigger>
        <Trigger Property="IsMouseOver"
                 Value="true">
            <Trigger.ExitActions>
                <BeginStoryboard Storyboard="{StaticResource HoverOff}"
                                 x:Name="HoverOff_BeginStoryboard" />
            </Trigger.ExitActions>
            <Trigger.EnterActions>
                <BeginStoryboard Storyboard="{StaticResource HoverOn}" />
            </Trigger.EnterActions>

        </Trigger>
        <Trigger Property="IsChecked"
                 Value="true">
            <Trigger.ExitActions>
                <BeginStoryboard Storyboard="{StaticResource CheckedOff}"
                                 x:Name="CheckedOff_BeginStoryboard" />
            </Trigger.ExitActions>
            <Trigger.EnterActions>
                <BeginStoryboard Storyboard="{StaticResource CheckedOn}"
                                 x:Name="CheckedOn_BeginStoryboard" />
            </Trigger.EnterActions>
        </Trigger>
        <Trigger Property="IsEnabled"
                 Value="False">
            <Setter Property="Foreground"
                    Value="{DynamicResource DisabledForegroundBrush}" />
            <Setter Property="Visibility"
                    TargetName="DisabledVisualElement"
                    Value="Visible" />
            <Setter Property="Fill"
                    TargetName="Background"
                    Value="{DynamicResource DisabledBackgroundBrush}" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<ControlTemplate x:Key="ComboBoxTextBox"
                 TargetType="{x:Type TextBox}">
    <Border x:Name="PART_ContentHost"
            Focusable="False"
            Background="{TemplateBinding Background}" />
</ControlTemplate>

<Style TargetType="{x:Type ComboBox}">
    <Setter Property="SnapsToDevicePixels"
            Value="true" />
    <Setter Property="HorizontalContentAlignment"
            Value="Stretch" />
    <Setter Property="VerticalContentAlignment"
            Value="Center" />
    <Setter Property="FontSize"
            Value="13" />
    <Setter Property="FontWeight"
            Value="Bold" />
    <Setter Property="Padding"
            Value="6,2,25,2" />
    <Setter Property="Margin"
            Value="3" />
    <Setter Property="ToolTipService.ShowOnDisabled"
            Value="True" />
    <Setter Property="Template"
            Value="{DynamicResource ComboBoxTemplate}" />
    <Setter Property="Validation.ErrorTemplate"
            Value="{StaticResource SablonaChybovehoHlaseni}" />
</Style>

<ControlTemplate x:Key="ComboBoxTemplate"
                 TargetType="{x:Type ComboBox}">
    <ControlTemplate.Resources>
        <Storyboard x:Key="FocusedOn">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="FocusVisualElement"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
                                      Value="1" />
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="FocusedOff">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="FocusVisualElement"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00.3000000"
                                      Value="0" />
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </ControlTemplate.Resources>
    <Grid>
        <ToggleButton Grid.Column="2"
                      Template="{DynamicResource ComboBoxToggleButton}"
                      x:Name="ToggleButton"
                      Focusable="false"
                      IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                      ClickMode="Press" />
        <ContentPresenter HorizontalAlignment="Stretch"
                          Margin="3,3,23,3"
                          x:Name="ContentSite"
                          VerticalAlignment="Top"
                          Content="{TemplateBinding SelectionBoxItem}"
                          ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                          IsHitTestVisible="True">
            <ContentPresenter.ContentTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}"
                               TextWrapping="Wrap" />
                </DataTemplate>
            </ContentPresenter.ContentTemplate>
        </ContentPresenter>
        <!--Textbox for ComboBox-->
        <!--Set transparent background of TextBox-->
        <TextBox Visibility="Hidden"
                 Template="{DynamicResource ComboBoxTextBox}"
                 HorizontalAlignment="Stretch"
                 Margin="3,3,23,3"
                 x:Name="PART_EditableTextBox"
                 Style="{x:Null}"
                 VerticalAlignment="Top"
                 Focusable="True"
                 Background="Transparent"
                 TextWrapping="Wrap"
                 IsReadOnly="{TemplateBinding IsReadOnly}" />
        <Rectangle x:Name="DisabledVisualElement"
                   Fill="{DynamicResource DisabledBackgroundBrush}"
                   Stroke="{DynamicResource DisabledBorderBrush}"
                   RadiusX="3"
                   RadiusY="3"
                   IsHitTestVisible="false"
                   Opacity="0" />
        <Rectangle x:Name="FocusVisualElement"
                   Margin="-1"
                   RadiusX="3"
                   RadiusY="3"
                   Stroke="{DynamicResource FocusBrush}"
                   StrokeThickness="1"
                   IsHitTestVisible="false"
                   Opacity="0" />
        <Popup IsOpen="{TemplateBinding IsDropDownOpen}"
               Placement="Bottom"
               x:Name="Popup"
               Focusable="False"
               AllowsTransparency="True"
               PopupAnimation="Slide"
               Margin="0,1,0,0">
            <Grid MaxHeight="{TemplateBinding MaxDropDownHeight}"
                  MinWidth="{TemplateBinding ActualWidth}"
                  x:Name="DropDown"
                  SnapsToDevicePixels="True">
                <Border x:Name="DropDownBorder"
                        Margin="0,-1,0,0"
                        BorderBrush="{DynamicResource ControlBorderBrush}"
                        BorderThickness="1"
                        CornerRadius="0,0,3,3"
                        Background="{DynamicResource WhiteColorBrush}">
                    <!--ControlBackgroundBrush-->
                    <ScrollViewer Margin="4,6,4,6"
                                  SnapsToDevicePixels="True"
                                  HorizontalScrollBarVisibility="Auto"
                                  VerticalScrollBarVisibility="Auto"
                                  CanContentScroll="True">
                        <StackPanel IsItemsHost="True"
                                    KeyboardNavigation.DirectionalNavigation="Contained" />

                    </ScrollViewer>
                </Border>
            </Grid>
        </Popup>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsFocused"
                 Value="True">
            <Trigger.ExitActions>
                <BeginStoryboard Storyboard="{StaticResource FocusedOff}"
                                 x:Name="FocusedOff_BeginStoryboard" />
            </Trigger.ExitActions>
            <Trigger.EnterActions>
                <BeginStoryboard Storyboard="{StaticResource FocusedOn}" />
            </Trigger.EnterActions>
            <Setter Property="CornerRadius"
                    TargetName="DropDownBorder"
                    Value="3" />
        </Trigger>
        <Trigger Property="HasItems"
                 Value="false">
            <Setter Property="MinHeight"
                    Value="95"
                    TargetName="DropDownBorder" />
        </Trigger>
        <Trigger Property="IsEnabled"
                 Value="false">
            <Setter Property="Foreground"
                    Value="{DynamicResource DisabledForegroundBrush}" />
            <Setter Property="Opacity"
                    TargetName="DisabledVisualElement"
                    Value="1" />
        </Trigger>
        <Trigger Property="IsGrouping"
                 Value="true">
            <Setter Property="ScrollViewer.CanContentScroll"
                    Value="false" />
        </Trigger>
        <Trigger Property="AllowsTransparency"
                 SourceName="Popup"
                 Value="true">
            <Setter Property="CornerRadius"
                    Value="4"
                    TargetName="DropDownBorder" />
            <Setter Property="Margin"
                    Value="0,2,0,0"
                    TargetName="DropDownBorder" />
        </Trigger>
        <Trigger Property="IsEditable"
                 Value="true">
            <Setter Property="IsTabStop"
                    Value="false" />
            <Setter Property="Visibility"
                    Value="Visible"
                    TargetName="PART_EditableTextBox" />
            <Setter Property="Visibility"
                    Value="Hidden"
                    TargetName="ContentSite" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

【问题讨论】:

    标签: wpf xaml combobox styles


    【解决方案1】:

    ComboBox 有两个用例。第一个是 IsEditable 为 false 时。在这种情况下,用户仅限于选择预定义的项目。第二种是 IsEditable 为 true 时,这种情况下允许用户输入文本以及选择预定义的项目。

    使用默认 Aero 样式,单击“文本”区域(即当 IsEditable 为 true 时)不会弹出下拉菜单。单击焦点/选择文本。不过其他样式会打开下拉菜单。

    为了实现这一点,在另一个控件的顶部放置了一个透明的 ToggleButton,用于切换下拉列表的可见性。比如:

    <Grid Grid.IsSharedSizeScope="true">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"
                              SharedSizeGroup="ComboBoxButton"/>
        </Grid.ColumnDefinitions>
        <TextBox x:Name="PART_EditableTextBox"
                 Grid.Column="1"
                 Style="{StaticResource ComboBoxEditableTextBox}"
                 IsReadOnly="{Binding Path=IsReadOnly,RelativeSource={RelativeSource TemplatedParent}}"
                 Margin="{TemplateBinding Padding}"
                 HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                 VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
        <ToggleButton Background="{x:Null}"
                      Grid.ColumnSpan="3"
                      Style="{StaticResource ComboBoxTransparentButtonStyle}"
                      IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"/>
    </Grid>
    

    这是从 Luna 的默认样式中提取的,您可以从 here 获得(或直接从 here 下载)。

    【讨论】:

    • 谢谢你,你让我找到了正确的方向。我通过在其他控件之上添加一个不可见的 ToggleButton 来解决它,如您的示例所示:&lt;ToggleButton Grid.ColumnSpan="3" Opacity="0" Focusable="false" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" /&gt;
    猜你喜欢
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    相关资源
    最近更新 更多