WPF ComboBox:如何将焦点设置在其切换按钮上
我正在尝试让 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
的焦点状态,但是这在触发器
内部不起作用。
任何帮助表示赞赏。抱歉这个菜鸟问题。谢谢!
I'm trying to get a ComboBox
to match a visual design, so its ToggleButton
has a blue border when the ComboBox
has focus. I can't figure out how to do this and can't find an example.
When the ComboBox
gets focus, the TextBox
inside gets the dashed focus visual. How do I pass the ComboBox
focus state down to the ToggleButton
, so that it's blue border style is turned on?
Here is my ComboBox
template:
<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>
And here's my ToggleButton
template:
<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>
As you can see I try to bind to the ComboBox
's focus state, but that doesn't work inside the Trigger
.
Any help appreciated. Sorry for the noob question. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
最简单的方法是绑定到模板父项的 IsFocused。注意:Mode=OneWay 很重要,因为 IsFocused 是只读的。你可以这样做:
The easiest way to do this is to have a binding to the Templated Parent's IsFocused. Note: Mode=OneWay is important since IsFocused is read only. You could do something like this:
您想要自定义或选择 FocusVisualStyle:
参见这里:
MSDN:控件中焦点的样式和 FocusVisualStyle
我认为蓝色的您想要的是来自一些原始的 Windows 主题,也许它包含在此下载中 默认 WPF 主题,来自 Microsoft WPF 示例。
You want to customize or chose a FocusVisualStyle:
See here:
MSDN: Styling for Focus in Controls, and FocusVisualStyle
I think the blue one you want to have is from some original windows theme, maybe it's contained in this download Default WPF Themes from Microsoft WPF Samples.
您已在 ControlTemplate 中为 ToggleButton 设置了
Focusable=False
,因此当它收到焦点时,会将焦点传递给下一个内部可聚焦 UIElement。如果删除它,您的 ToggleButton 应该获得焦点,而不是 TextBox。
You have set
Focusable=False
for your ToggleButton in the ControlTemplate, so when it receives the focus, it passes it down to the next inner focusable UIElement.If you remove that, your ToggleButton should get the focus instead of the TextBox.
当您将
ComboBox.IsEditable
属性设置为True
时,绑定到模板化父项的IsFocused
属性不起作用。相反,您可以使用IsKeyboardFocusWithin
,检查以下内容:Binding to the templated parent's
IsFocused
prperty do not work when you set theComboBox.IsEditable
property toTrue
. Instead you can useIsKeyboardFocusWithin
, check the following: