当子 TextBox 获得焦点时设置 ListBoxItem.IsSelected
我有一个典型的 MVVM 场景: 我有一个绑定到 StepsViewModels 列表的列表框。 我定义了一个 DataTemplate,以便 StepViewModel 呈现为 StepView。 StepView UserControl 有一组标签和文本框。
我想要做的是选择当文本框聚焦时包裹 StepView 的 ListBoxItem。我尝试使用以下触发器为我的 TextBox 创建样式:
<Trigger Property="IsFocused" Value="true">
<Setter TargetName="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" Property="IsSelected" Value="True"/>
</Trigger>
但我收到一条错误消息,告诉我 TextBox 没有 IsSelected 属性。我现在知道目标是一个 ListBoxItem。 我怎样才能让它发挥作用?
I have a typical MVVM scenario:
I have a ListBox that is binded to a List of StepsViewModels.
I define a DataTemplate so that StepViewModels are rendered as StepViews.
The StepView UserControl have a set of labels and TextBoxs.
What I want to do is to select the ListBoxItem that is wrapping the StepView when a textBox is focused. I've tried to create a style for my TextBoxs with the following trigger:
<Trigger Property="IsFocused" Value="true">
<Setter TargetName="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" Property="IsSelected" Value="True"/>
</Trigger>
But I get an error telling me that TextBoxs don't have an IsSelected property. I now that but the Target is a ListBoxItem.
How can I make it work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
有一个只读属性 IsKeyboardFocusWithin,如果任何子项获得焦点,该属性将设置为 true。您可以使用它在触发器中设置 ListBoxItem.IsSelected:
There is a read-only property IsKeyboardFocusWithin that will be set to true if any child is focused. You can use this to set ListBoxItem.IsSelected in a Trigger:
正如 Jordan0Day 正确指出的那样,使用 IsKeyboardFocusWithin 解决方案确实可能会出现大问题。就我而言,工具栏中与列表框相关的按钮也不再起作用。对焦也有同样的问题。单击按钮时,ListBoxItem 确实会失去焦点,并且按钮会更新其 CanExecute 方法,这会导致在执行按钮单击命令之前禁用该按钮。
对我来说,更好的解决方案是使用 ItemContainerStyle EventSetter,如这篇文章中所述: 使用内部控件时的ListboxItem选择
XAML:
视图后面代码中的EventHandler:
As Jordan0Day correctly pointed out there can be indeed big problems using IsKeyboardFocusWithin solution. In my case a Button in a Toolbar which regards to the ListBox was also not working anymore. The same problem with focus. When clicking the button the ListBoxItem does loose the Focus and the Button updated its CanExecute method, which resulted in disabling the button just a moment before the button click command should be executed.
For me a much better solution was to use a ItemContainerStyle EventSetter as described in this post: ListboxItem selection when the controls inside are used
XAML:
EventHandler in the code behind of the view:
实现此目的的一种方法是使用附加属性实现自定义行为。基本上,附加属性将使用样式应用于
ListBoxItem
,并连接到其GotFocus
事件。如果控件的任何后代获得焦点,它甚至会触发,因此它适合此任务。在事件处理程序中,IsSelected
设置为true
。我为您编写了一个小示例:
行为类:
窗口 XAML:
用户控件 XAML:
One way to achieve that is by implementing a custom behavior using an attached property. Basically, the attached property would be applied to the
ListBoxItem
using a style, and would hook up to theirGotFocus
event. That even fires if any descendant of the control gets the focus, so it is suitable for this task. In the event handler,IsSelected
is set totrue
.I wrote up a small example for you:
The Behavior Class:
The Window XAML:
The User Control XAML:
如果您创建一个用户控件,然后将其用作数据模板,它似乎工作得更干净。
那么您就不必使用 100% 情况下都不起作用的脏样式触发器。
If you create a User Control and then use it as the DataTemplate It seems to work cleaner.
Then you don't have to use the dirty Style Triggers that Don't work 100% of the time.
编辑:其他人已经在不同的问题上有相同的答案:https://stackoverflow.com/a/7555852/2484737
继续 Maexs 的回答,使用 EventTrigger 而不是 EventSetter 消除了对代码隐藏的需要:
Edit: Someone else already had the same answer on a different question: https://stackoverflow.com/a/7555852/2484737
Continuing on Maexs' answer, using an EventTrigger instead of an EventSetter removes the need for code-behind: