当其内部 ComboBox 获得焦点时选择 ListBoxItem

发布于 2024-08-05 15:26:30 字数 815 浏览 3 评论 0原文

我有一个 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}" />

I have a DataTemplate that will be a templated ListBoxItem, this DataTemplate has a
ComboBox in it which when it has focus I want the ListBoxItem that this template
represents to become selected, this looks right to me. but sadly enough it doesn't work =(

So the real question here is within a DataTemplate is it possible to get or set the value
of the ListBoxItem.IsSelected property via a 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}" />

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

星星的軌跡 2024-08-12 15:26:30

我找到了解决你问题的方法。

问题是,当您的列表框项上有一个控件并且单击该控件(例如输入文本或更改组合框的值)时,不会选择 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,因为SelectedItem of Treeview只读
因此,如果您能帮我解决树视图问题;-)

I found a solution for your problem.

The problem is that when you have a control on your listboxitem, and the control is clicked (like for inputting text or changing the value of a combobox), the ListBoxItem does not get selected.

this should do the job:

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

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

--> Use this FocusableListBox in stead of the default ListBox of WPF.

And use this 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 does also have this problem, but this solution does not work for a Treeview, 'cause SelectedItem of Treeview is readonly.
So if you can help me out with the Treeview please ;-)

温柔嚣张 2024-08-12 15:26:30

我发现我更喜欢使用这个:

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

简单并且适用于所有列表框项目,无论里面有什么。

I found that I preferred to use this:

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

Simple and works for all the listboxitems, regardless of what's inside.

毁我热情 2024-08-12 15:26:30

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

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);
            }
        }
    }
}

No idea why your trigger don't work. To catch the get focus event of the combo box (or any control inside a listbox item) you can use attached routed events. You could put the code also in a derived listbox if you need this behavior in other parts of your application.

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>

Code behind hooking up to all got focus events.

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);
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文