【问题标题】:WPF Treeview loses focus when Context Menu is open上下文菜单打开时 WPF Treeview 失去焦点
【发布时间】:2015-02-02 07:24:19
【问题描述】:

Visual Studio 中的 TreeView(例如解决方案资源管理器)具有以下行为:

  • 如果 TreeView 有焦点,则选中的项目以蓝色突出显示;
  • 如果焦点从 TreeView 移开,所选项目变为灰色;
  • 如果在项目上打开上下文菜单,则项目变为蓝色并在上下文菜单在屏幕上时保持蓝色

但是在 WPF 库存的 TreeView 中,项目的上下文菜单会从 TreeView 中窃取焦点,并且当显示上下文菜单时,选定的项目会变为灰色。但是,窗口菜单行为正常且不会窃取焦点。

如何让我的程序表现得像 VS?我知道我可以将不活动的高光画笔调整为蓝色,但在这种情况下,当 TreeView 真的失去焦点时,选定的项目不会变成灰色。

【问题讨论】:

  • 看看this的回答。似乎做你想做的事。

标签: wpf focus contextmenu


【解决方案1】:

将每个ContextMenuItemContextMenu 本身的Focusable 属性设置为False,你会得到你想要的:

<Grid >
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>            
    </Grid.RowDefinitions>
    <Menu>
        <MenuItem Header="Item1">                
                <MenuItem Header="Sub Item 1"></MenuItem>
                <MenuItem Header="Sub Item 2"></MenuItem>
                <MenuItem Header="Sub Item 3"></MenuItem>                                    
        </MenuItem>
        <MenuItem Header="Item2">
            <MenuItem Header="Sub Item 1"></MenuItem>
            <MenuItem Header="Sub Item 2"></MenuItem>
            <MenuItem Header="Sub Item 3"></MenuItem>
        </MenuItem>
    </Menu>
    <TreeView Grid.Row="1">
        <TreeView.ContextMenu>
            <ContextMenu Focusable="False">
                <MenuItem Header="Ctx1" Focusable="False"></MenuItem>
                <MenuItem Header="Ctx2" Focusable="False"></MenuItem>
                <MenuItem Header="Ctx3" Focusable="False"></MenuItem>
            </ContextMenu>
        </TreeView.ContextMenu>
        <TreeViewItem Header="ItemOne">
            <TreeViewItem Header="Sub Item 1"></TreeViewItem>
            <TreeViewItem Header="Sub Item 2"></TreeViewItem>
            <TreeViewItem Header="Sub Item 3"></TreeViewItem>
        </TreeViewItem>
    </TreeView>        
</Grid>

输出:

【讨论】:

  • 这个解决方案乍一看似乎很好,但有一个缺点:由于真正的焦点仍然在 TreeView 上,按键盘上的箭头键会导致在 TreeView 上导航,而不是在上下文菜单上导航。
【解决方案2】:

我发现这是由于TreeViewItem 的默认样式在Selector.IsSelectionActive 附加属性上有一个触发器。如果您更改此设置以触发 IsFocused,我认为您将获得您所追求的行为。

它可以工作,因为虽然 ContextMenu 带走了键盘焦点(并导致 IsSelectionActive 设置为 false),但原始窗口保留了它的逻辑焦点。

这是我在 Visual Studio 中创建的样式,方法是右键单击设计器中的“现成”TreeViewItem,然后单击“编辑模板”、“编辑副本...”。然后我将Selector.IsSelectionActive 替换为IsFocused

<SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Fill" Color="#FF595959"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Stroke" Color="#FF262626"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Stroke" Color="#FF27C7F7"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Fill" Color="#FFCCEEFB"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Stroke" Color="#FF1CC4F7"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Fill" Color="#FF82DFFB"/>
<PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Fill" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Stroke" Color="#FF818181"/>
<Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Width" Value="16"/>
    <Setter Property="Height" Value="16"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Border Background="Transparent" Height="16" Padding="5,5,5,5" Width="16">
                    <Path x:Name="ExpandPath" Data="{StaticResource TreeArrow}" Fill="{StaticResource TreeViewItem.TreeArrow.Static.Fill}" Stroke="{StaticResource TreeViewItem.TreeArrow.Static.Stroke}">
                        <Path.RenderTransform>
                            <RotateTransform Angle="135" CenterY="3" CenterX="3"/>
                        </Path.RenderTransform>
                    </Path>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter Property="RenderTransform" TargetName="ExpandPath">
                            <Setter.Value>
                                <RotateTransform Angle="180" CenterY="3" CenterX="3"/>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.Static.Checked.Fill}"/>
                        <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.Static.Checked.Stroke}"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Stroke}"/>
                        <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Fill}"/>
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsMouseOver" Value="True"/>
                            <Condition Property="IsChecked" Value="True"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Checked.Stroke}"/>
                        <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Checked.Fill}"/>
                    </MultiTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
    <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
    <Setter Property="Padding" Value="1,0,0,0"/>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TreeViewItem}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition MinWidth="19" Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                        <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                    <ItemsPresenter x:Name="ItemsHost" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsExpanded" Value="false">
                        <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
                    </Trigger>
                    <Trigger Property="HasItems" Value="false">
                        <Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
                    </Trigger>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true"/>
                            <Condition Property="IsFocused" Value="false"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
                    </MultiTrigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </Trigger>
    </Style.Triggers>
</Style>

【讨论】:

    猜你喜欢
    • 2011-05-25
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 2013-07-26
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多