WPF ComboBox:如何将焦点设置在其ToggleButton上

3
我正在尝试使ComboBox与视觉设计相匹配,因此当ComboBox获得焦点时,它的ToggleButton具有蓝色边框。我无法弄清楚如何实现这一点,并且找不到示例。
ComboBox获得焦点时,内部的TextBox会显示虚线焦点可视化效果。我应该如何将ComboBox的焦点状态传递给ToggleButton,以便打开其蓝色边框样式?
这是我的ComboBox模板:
<ControlTemplate x:Key="ComboBoxCT" TargetType="{x:Type ComboBox}">
    <Grid x:Name="gLayoutRoot"
        Margin="{TemplateBinding Margin}" 
        HorizontalAlignment="{TemplateBinding HorizontalAlignment}" 
        VerticalAlignment="{TemplateBinding VerticalAlignment}" 
        MinWidth="{TemplateBinding MinWidth}" 
        MinHeight="{TemplateBinding MinHeight}" 
        MaxWidth="{TemplateBinding MaxWidth}" 
        MaxHeight="{TemplateBinding MaxHeight}" 
        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
        <ToggleButton x:Name="ToggleButton" 
            Grid.Column="2" 
            Focusable="false"
            IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
            ClickMode="Press" 
            Style="{DynamicResource ComboBoxToggleStyle}" 
            />
        <AccessText x:Name="ContentSite" 
            Style="{StaticResource ComboBoxAccessTextStyle}" 
            Text="{TemplateBinding SelectionBoxItem}" 
            Foreground="{TemplateBinding Foreground}"/>
        <TextBox x:Name="PART_EditableTextBox"
            Style="{x:Null}" 
            HorizontalAlignment="{TemplateBinding HorizontalAlignment}" 
            VerticalAlignment="{TemplateBinding VerticalAlignment}" 
            Margin="2,3,17,2"
            Focusable="True" 
            Background="{DynamicResource InnerBgLight}"
            Visibility="Hidden"
            IsReadOnly="{TemplateBinding IsReadOnly}">
            <TextBox.Template>
                <ControlTemplate TargetType="TextBox">
                    <Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}" />
                </ControlTemplate>
            </TextBox.Template>
        </TextBox>
        <Popup x:Name="Popup"
            Placement="Bottom"
            IsOpen="{TemplateBinding IsDropDownOpen}"
            AllowsTransparency="True" 
            Focusable="False"
            PopupAnimation="Slide">
                <Grid x:Name="DropDown"
                    SnapsToDevicePixels="True"                
                    MinWidth="{TemplateBinding ActualWidth}"
                    MaxHeight="{TemplateBinding MaxDropDownHeight}">
                        <Border x:Name="OuterBorder"
                            Style="{DynamicResource OuterBorderBottomRestStyle}"
                            Background="{DynamicResource InnerBorder}">
                            <Border x:Name="InnerBorder" 
                                Style="{DynamicResource InnerBottomBorderStyle}">
                                <ScrollViewer x:Name="scvCbxItems" SnapsToDevicePixels="True">
                                    <StackPanel x:Name="spCbxItemsPanel" IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
                                </ScrollViewer>
                            </Border>
                        </Border>
                </Grid>
            </Popup>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="HasItems" Value="false">
                <Setter TargetName="InnerBorder" Property="MinHeight" Value="95"/>
            </Trigger>
            <Trigger Property="IsGrouping" Value="true">
                <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
            </Trigger>
            <Trigger Property="IsEditable" Value="true">
                <Setter Property="IsTabStop" Value="false"/>
                <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
                <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
            </Trigger>
            <Trigger Property="IsEnabled" Value="false">
                <Setter Property="Foreground" Value="{DynamicResource FgDisabledBrush}"/>
                <Setter Property="OpacityMask" TargetName="OuterBorder" Value="{DynamicResource OuterBgDisabledOpacityMask}"/>
            </Trigger>  
        </ControlTemplate.Triggers>
    </ControlTemplate>

这是我的 ToggleButton 模板:

    <ControlTemplate x:Key="ComboBoxToggleCT" TargetType="{x:Type ToggleButton}">
    <Border x:Name="OuterBorder" 
        Style="{DynamicResource OuterBorderTopRestStyle}">
        <Border x:Name="InnerBorder" 
            Style="{DynamicResource InnerTopBorderStyle}">
                <Path x:Name="Arrow" 
                    HorizontalAlignment="Right" VerticalAlignment="Center"
                    Margin="5"
                    Fill="{DynamicResource FgBrush}"
                    Data="{DynamicResource DownArrowGeometry}"/>
        </Border>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Style" TargetName="OuterBorder" Value="{DynamicResource OuterBorderTopSelectStyle}"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="OpacityMask" TargetName="OuterBorder" Value="{DynamicResource OuterBgDisabledOpacityMask}"/>
            <Setter Property="Fill" TargetName="Arrow" Value="{DynamicResource FgDisabledBrush}"/>
        </Trigger>
        <Trigger Property="IsPressed" Value="True">
            <Setter Property="Style" TargetName="OuterBorder" Value="{DynamicResource OuterBorderTopSelectStyle}"/>
            <Setter Property="Style" TargetName="InnerBorder" Value="{DynamicResource InnerBorderTopFocusStyle}"/>
        </Trigger>
        <!--<Trigger Property="IsKeyboardFocused" Value="True">-->
        <Trigger Property="IsKeyboardFocused" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsFocused}">
            <Setter Property="Style" TargetName="OuterBorder" Value="{DynamicResource OuterBorderBottomFocusStyle}"/>
            <Setter Property="Style" TargetName="InnerBorder" Value="{DynamicResource InnerBorderTopFocusStyle}"/>
        </Trigger>
    </ControlTemplate.Triggers>

</ControlTemplate>

正如您所看到的,我试图绑定到ComboBox的焦点状态,但在Trigger内部无法工作。

非常感谢任何帮助。对于这个初学者问题表示抱歉。谢谢!

4个回答

4

最简单的方法是将绑定设置为Templated Parent的IsFocused属性。注意:Mode=OneWay很重要,因为IsFocused是只读的。你可以这样做:

<DataTrigger Binding="{Binding IsFocused, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}" Value="True">
   <Setter Property="Style" TargetName="OuterBorder" Value="{DynamicResource OuterBorderBottomFocusStyle}"/>
   <Setter Property="Style" TargetName="InnerBorder" Value="{DynamicResource InnerBorderTopFocusStyle}"/>
</DataTrigger >

0

当您将ComboBox.IsEditable属性设置为True时,绑定到模板父级的IsFocused属性不起作用。相反,您可以使用IsKeyboardFocusWithin,请参考以下内容:

<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}" Value="True">
    <Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorLight}" />
    <Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorLight}" />
    <Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorLight}" />
    <Setter Property="Fill" TargetName="Arrow" Value="White" />
</DataTrigger >

0

焦点视觉仅在控件内部的文本框周围绘制框。我想要样式化切换按钮,使整个按钮都被突出显示。 - dex3703

0

您在控件模板中将 Focusable=False 设置为了 ToggleButton,因此当它获得焦点时,会将焦点传递给下一个可聚焦的 UIElement。 如果您将其移除,则您的 ToggleButton 应该会获得焦点,而不是 TextBox。


这样做会导致组合框获得两次焦点——您会在组合框周围看到虚线,然后进入切换按钮。您需要按两次Tab键才能停留在组合框上。 - dex3703
UISpy在切换到ToggleButton时没有注册,当您两次按Tab键时它仍然停留在“ComboBox”上。我想要一个ComboBox的单个焦点事件。当ComboBox可编辑时,TextBox也需要接收焦点。 - dex3703

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接