Выбор ListBoxItem, когда его внутренний ComboBox сфокусирован - PullRequest
12 голосов
/ 22 сентября 2009

У меня есть DataTemplate, который будет шаблонным ListBoxItem, этот DataTemplate имеет ComboBox в нем, который, когда он имеет фокус, я хочу ListBoxItem, что этот шаблон представляет стать избранным, это выглядит правильно для меня. но, к сожалению, это не работает = (

Таким образом, реальный вопрос здесь в шаблоне данных: возможно ли получить или установить значение? свойства ListBoxItem.IsSelected через DataTemplate.Trigger?

<DataTemplate x:Key="myDataTemplate" 
              DataType="{x:Type local:myTemplateItem}">

 <Grid x:Name="_LayoutRoot">
     <ComboBox x:Name="testComboBox" />
 </Grid>

 <DataTemplate.Triggers>
     <Trigger Property="IsFocused" value="true" SourceName="testComboBox">
         <Setter Property="ListBoxItem.IsSelected" Value="true" />
     </Trigger>
 </DataTemplate.Triggers>

</DataTemplate>

<ListBox ItemTemplate="{StaticResource myDataTemplate}" />

Ответы [ 3 ]

9 голосов
/ 22 сентября 2009

Я нашел решение вашей проблемы.

Проблема в том, что когда у вас есть элемент управления в элементе списка, и элемент управления щелкается (например, для ввода текста или изменения значения комбинированного списка), ListBoxItem не выбирается.

это должно сделать работу:

public class FocusableListBox : ListBox
{
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return (item is FocusableListBoxItem);
    }

    protected override System.Windows.DependencyObject GetContainerForItemOverride()
    {
        return new FocusableListBoxItem();
    }
}

-> Используйте этот FocusableListBox вместо стандартного ListBox WPF.

И используйте этот ListBoxItem:

public class FocusableListBoxItem : ListBoxItem
{
    public FocusableListBoxItem()
    {
        GotFocus += new RoutedEventHandler(FocusableListBoxItem_GotFocus);
    }


    void FocusableListBoxItem_GotFocus(object sender, RoutedEventArgs e)
    {
        object obj = ParentListBox.ItemContainerGenerator.ItemFromContainer(this);
        ParentListBox.SelectedItem = obj;
    }

    private ListBox ParentListBox
    {
        get
        {
            return (ItemsControl.ItemsControlFromItemContainer(this) as ListBox);
        }
    }

}

A Treeview также имеет эту проблему, но это решение не работает для Treeview, потому что SelectedItem из Treeview равно readonly. Так что, если вы можете помочь мне с Treeview, пожалуйста; -)

8 голосов
/ 04 января 2012

Я обнаружил, что предпочел использовать это:

<Style  TargetType="ListBoxItem">
    <Style.Triggers>
        <Trigger Property="IsKeyboardFocusWithin" Value="True">
             <Setter Property="IsSelected" Value="True"></Setter>
        </Trigger>
    </Style.Triggers>
</Style>

Простой и работает для всех элементов списка, независимо от того, что внутри.

0 голосов
/ 24 сентября 2009

Не знаю, почему ваш триггер не работает. Чтобы перехватить событие получения фокуса поля со списком (или любого элемента управления внутри элемента списка), вы можете использовать вложенные перенаправленные события. Вы также можете поместить код в производное окно списка, если вам нужно такое поведение в других частях вашего приложения.

XAML:

<Window x:Class="RoutedEventDemo.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Specialized="clr-namespace:System.Collections.Specialized;assembly=System"
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    Height="300" Width="300">

    <Window.Resources>

        <DataTemplate x:Key="myDataTemplate">
            <Grid>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding}" Margin="5,0"/>
                    <ComboBox Width="50">
                        <ComboBoxItem>AAA</ComboBoxItem>
                        <ComboBoxItem>BBB</ComboBoxItem>
                    </ComboBox>
                </StackPanel>
            </Grid>
        </DataTemplate>

    </Window.Resources>

    <Grid>

        <ListBox ItemTemplate="{StaticResource myDataTemplate}">
            <ListBox.ItemsSource>
                <Specialized:StringCollection>
                    <System:String>Item 1</System:String>
                    <System:String>Item 2</System:String>
                    <System:String>Item 3</System:String> 
                </Specialized:StringCollection>
            </ListBox.ItemsSource>
        </ListBox>

    </Grid>
</Window>

Код для подключения ко всем полученным событиям фокуса.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace RoutedEventDemo
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            EventManager.RegisterClassHandler(typeof(UIElement),
                                              GotFocusEvent,
                                              new RoutedEventHandler(OnGotFocus));
        }

        private static void OnGotFocus(object sender, RoutedEventArgs e)
        {
            // Check if element that got focus is contained by a listboxitem and
            // in that case selected the listboxitem.

            DependencyObject parent = e.OriginalSource as DependencyObject;
            while (parent != null)
            {
                ListBoxItem clickedOnItem = parent as ListBoxItem;
                if (clickedOnItem != null)
                {
                    clickedOnItem.IsSelected = true;
                    return;
                }

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