How to use IsKeyboardFocusWithin and IsSelected together?

I have a style defined for mine ListBoxItemswith a trigger to set the background color when IsSelectedTrue:

    <Style x:Key="StepItemStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="SnapsToDevicePixels" Value="true"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Border Name="Border" Padding="0" SnapsToDevicePixels="true">
                        <ContentPresenter />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter TargetName="Border" Property="Background" Value="#40a0f5ff"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

This style supports the selected item, even if the tags ListBoxand ListBoxItemlose focus, which in my case is an absolute must. The problem is that I also want to be ListBoxItemselected when one of its children is TextBoxfocused. To do this, I add a trigger that sets IsSelectedto true, if IsKeyboardFocusWithintrue:

<Trigger Property="IsKeyboardFocusWithin" Value="True">
    <Setter Property="IsSelected" Value="True" />
</Trigger>

When I add this trigger, the element is selected when the focus is on the child TextBox, but the first behavior disappears. Now when I go beyond ListBox, the item is not selected.

?

+5
3

, null - . , - , , .

XAML:

<Window x:Class="SelectedTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">

    <StackPanel>
        <TextBox Text="Loose focus here" />
        <ListBox Name="_listBox" ItemsSource="{Binding Path=Items}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" GotFocus="OnChildGotFocus">
                        <TextBox Text="{Binding .}" Margin="10" />
                        <TextBox Text="{Binding .}" Margin="10" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="SnapsToDevicePixels" Value="true"/>
                    <Setter Property="OverridesDefaultStyle" Value="true"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListBoxItem">
                                <Border Name="Border" SnapsToDevicePixels="true" Background="Transparent">
                                    <ContentPresenter />
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="True">
                                        <Setter TargetName="Border" Property="Background" Value="Red"/>
                                    </Trigger>                                   
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
    </StackPanel>
</Window>

:

private void OnChildGotFocus(object sender, RoutedEventArgs e) 
{   
   _listBox.SelectedItem = (sender as StackPanel).DataContext; 
}
+6

, IsKeyboardFocusWithin .

, DataTemplate, GotFocus -event . , , ( VisualTreeHelper), ListViewItem IsSelected true. , "" DataContext View.

<Style TargetType="{x:Type Control}" x:Key="GridCellControlStyle">
...
<EventSetter Event="GotFocus" Handler="SelectListViewItemOnControlGotFocus"/>
...

private void SelectListViewItemOnControlGotFocus(object sender, RoutedEventArgs e)
{
var control = (Control)sender;
FocusParentListViewItem(control);
}

private void FocusParentListViewItem(Control control)
{
var listViewItem = FindVisualParent<ListViewItem>(control);
if (listViewItem != null)
    listViewItem.IsSelected = true;
}

public static T FindVisualParent<T>(UIElement element) where T : UIElement
{
UIElement parent = element; 

while (parent != null)
{
    var correctlyTyped = parent as T; 

    if (correctlyTyped != null)
    {
        return correctlyTyped;
    }

    parent = VisualTreeHelper.GetParent(parent) as UIElement;
} 

return null;
}
+4

" , , TextBox, . , ListBox, ."

, , . , - , ListBoxItem . , , , , , .

, ListBoxItem , (: , "", , ) "Shift-Tab", , .

, , TextBox , ListBoxItem .

, , - .

- IsKeyboardFocusWithinChanged, "IsSelected" true, true. (. Sheridan faux, , , .) , , ..

( ) , , ListBoxItem, , , .

. . , . , ListBoxItem, UIElement. , ComboBoxItem, TreeViewItem .. ContainerItem .

public class AutoSelectWhenAnyChildGetsFocus
{
    public static readonly DependencyProperty EnabledProperty = DependencyProperty.RegisterAttached(
        "Enabled",
        typeof(bool),
        typeof(AutoSelectWhenAnyChildGetsFocus),
        new UIPropertyMetadata(false, Enabled_Changed));

    public static bool GetEnabled(DependencyObject obj){ return (bool)obj.GetValue(EnabledProperty); }
    public static void SetEnabled(DependencyObject obj, bool value){ obj.SetValue(EnabledProperty, value); }

    private static void Enabled_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var attachEvents = (bool)e.NewValue;
        var targetUiElement = (UIElement)sender;

        if(attachEvents)
            targetUiElement.IsKeyboardFocusWithinChanged += TargetUiElement_IsKeyboardFocusWithinChanged;
        else
            targetUiElement.IsKeyboardFocusWithinChanged -= TargetUiElement_IsKeyboardFocusWithinChanged;
    }

    static void TargetUiElement_IsKeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var targetUiElement = (UIElement)sender;

        if(targetUiElement.IsKeyboardFocusWithin)
            Selector.SetIsSelected(targetUiElement, true);
    }

}

... setter ListBoxItem

<Setter Property="behaviors:AutoSelectWhenAnyChildGetsFocus.Enabled" Value="True" />

, , , XML, "behaviors", , . "", . , , , , XAML, .

+4
source

All Articles