Listview选择“活动”项目

5

可能是重复问题:
如果ItemTemplate中的TextBox获得焦点,则选择ListBoxItem

我有一个绑定到ObservableCollectionListview.ItemsSource)的ListView。该列表视图呈现了几个文本框,这些文本框绑定到可观察集合中对象的属性。

我想要以下功能:当用户聚焦文本框时,应选择列表视图中相应的项目。

我已经尝试了ContainerFromElement、ContainerFromItem等方法,但无法使这个“简单”的功能正常工作。

有什么想法...

2个回答

6
这里的技巧是使用ItemContainerStyle上的IsKeyboardFocusWithin属性:
<ListView ItemsSource="{Binding}">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Style.Triggers>
                <Trigger Property="IsKeyboardFocusWithin" Value="True">
                    <Setter Property="IsSelected" Value="True" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Path=YourPropertyValue}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

在这个例子中,我们只需要说明当一个项目中的控件包含键盘焦点时,IsSelected应该被设置为true。
注意: 这样做是不会产生相反的效果的。在列表中选择一个特定的项目不会自动将焦点放在其中的TextBox上。
根据Joep的评论进行编辑,这意味着失去键盘焦点(例如当TextBox以外的控件获得焦点时)将导致IsSelected属性被重置为false。您可以通过用触发器进入操作替换Style setter来解决这个问题,这样当触发器不再有效时,更改就不会被撤消。
为了使它与之前的例子以相同的方式工作,您需要显式地将ListViewSelectionMode设置为Single;否则,可能会同时选择多个项目。
<ListView ItemsSource="{Binding}" SelectionMode="Single">
   <ListView.ItemContainerStyle>
       <Style TargetType="ListViewItem">
           <Style.Triggers>
               <Trigger Property="IsKeyboardFocusWithin" Value="True">
                   <Trigger.EnterActions>
                       <BeginStoryboard>
                           <Storyboard>
                               <BooleanAnimationUsingKeyFrames
                                  Storyboard.TargetProperty="IsSelected">
                                  <DiscreteBooleanKeyFrame KeyTime="0:0:0" 
                                     Value="True" />
                               </BooleanAnimationUsingKeyFrames>
                           </Storyboard>
                       </BeginStoryboard>
                   </Trigger.EnterActions>
               </Trigger>
           </Style.Triggers>
       </Style>
   </ListView.ItemContainerStyle>
   <!-- ... -->
</ListView>

太棒了!没有后台代码,只有一个样式触发器。优雅!它能正常工作... - Youp Bernoulli
解决方案引入了一个新问题。我有一些按钮“在”Listview之外,用于操作项目(添加、上移、下移、删除)。当我点击这些按钮时,焦点丢失并且Listview的SelectedItems变为null... - Youp Bernoulli
感谢你跟进你的回答 - 巨大的帮助。 - Steve Cadwallader

0

MVVM的方式会为ViewModel添加额外的属性,这些属性表示正在聚焦的属性。

例如,如果ViewModel有一个名为Name的属性,则添加一个IsNameFocussed属性,如果它有一个名为Address的属性,则添加一个IsAddressFocussed属性。

然后将DataTemplate中适当的控件绑定到Is...Focussed属性,以突出显示它。

最后,在文本框的GotFocus和LostFocus事件中设置Is...Focussed属性即可。(我更愿意绑定到一个Focussed属性,但它不存在...)


我不认为这是真正的“MVVM方式”。关键是使ViewModel不关心View,而将IsFocussed属性添加到其中会破坏这一点(至少在我看来是这样的)。 - Steve Greatrex
@SteveGreatrex,ViewModel确实关心Views,只是它不知道它们。 - Emond
好的,说得有道理,但是除非视图模型实际上需要知道焦点的知识(这在这里可能是或可能不是情况),否则包括这些属性仍然似乎很奇怪。 - Steve Greatrex
事实上,我曾经错误地假设TextBoxes紧邻着ListBox。在WPF中,触发器是一个很好的解决方案。 - Emond

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接