Wpf 当ListBoxItem的内部组合框处于焦点时选择它

Wpf 当ListBoxItem的内部组合框处于焦点时选择它,wpf,xaml,listbox,datatemplate,triggers,Wpf,Xaml,Listbox,Datatemplate,Triggers,我有一个DataTemplate,它将是一个模板化的ListBoxItem,这个DataTemplate有一个 ComboBox,当它有焦点时,我希望此模板包含ListBoxItem 表示要被选中,这在我看来是正确的。但遗憾的是,它不起作用=( 所以这里真正的问题是在DataTemplate中,是否可以获取或设置值 是否通过DataTemplate.Trigger选择ListBoxItem.IsSelected属性的 <DataTemplate x:Key="myDataTemplate"

我有一个DataTemplate,它将是一个模板化的ListBoxItem,这个DataTemplate有一个 ComboBox,当它有焦点时,我希望此模板包含ListBoxItem 表示要被选中,这在我看来是正确的。但遗憾的是,它不起作用=(

所以这里真正的问题是在DataTemplate中,是否可以获取或设置值 是否通过
DataTemplate.Trigger
选择
ListBoxItem.IsSelected属性的

<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}" />

我找到了解决您问题的方法

问题是,当您的listboxitem上有一个控件,并且单击该控件(例如用于输入文本或更改组合框的值)时,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代替WPF的默认ListBox

并使用此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);
        }
    }

}
Treeview
也存在此问题,但此解决方案不适用于
Treeview
,因为
Treeview
SelectedItem
只读的。

所以如果你能帮我看一下Treeview;-)

不知道你的触发器为什么不工作。要捕获组合框(或列表框项目内的任何控件)的get focus事件,可以使用附加的路由事件。如果在应用程序的其他部分需要这种行为,也可以将代码放在派生列表框中

XAML:


我发现我更喜欢用这个:

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


简单,适用于所有listboxitems,无论里面是什么。

解决了我的问题。事实上,我在这个问题上被难住了。解决方案的有趣方法。我很好奇,在XAML中是否有这样做的方法?不知道在XAML中是否可行。我很高兴它能在代码中工作:)每次我遇到这个问题时,你的答案都很有用。但是现在我在ListBoxItem上有一个Delete按钮,它的Focusable=False。在这种情况下,当单击此按钮时,旧的SelectedItem将被删除,而不是选择单击了“删除”按钮的项目,然后将其删除。您的答案有效,但单击按钮或任何其他控件后,我选择的索引将重置为-1
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);
            }
        }
    }
}
<Style  TargetType="ListBoxItem">
    <Style.Triggers>
        <Trigger Property="IsKeyboardFocusWithin" Value="True">
             <Setter Property="IsSelected" Value="True"></Setter>
        </Trigger>
    </Style.Triggers>
</Style>