ListViewItem focus

本文关键字:focus ListViewItem | 更新日期: 2023-09-27 18:12:50

使用MVVM:

<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" ... />

ViewModel:

public class Item: INotifyPropertyChanged { ... }
public ObservableCollection<Item> Items { get; set; }
public Item SelectedItem { get; set; }

如果我改变SelectedItem

// change
Items = new ObservableCollection<Item>(...);
SelectedItem = Items.FirstOrDefault(item => ... some condition);
// notify view
OnPropertyChanged();
OnPropertyChanged(nameof(SelectedItem));

然后想要的项目被正确选中,但它没有被聚焦。使用键盘导航,如果我以某种方式给ListView焦点,那么第一个项目将被选中并聚焦。

如何给予SelectedItem焦点?

ListViewItem focus

一种可能是在ListView有焦点时自动对焦所选的ListViewItem

xaml:

<ListView.ItemContainerStyle>
    <Style TargetType="ListViewItem">
        <EventSetter Event="Selected" Handler="ListViewItem_Selected" />
    </Style>
</ListView.ItemContainerStyle>

视图cs:

void ListViewItem_Selected(object sender, RoutedEventArgs e) 
{
    if (listView.IsFocused)
        (e.Source as ListViewItem)?.Focus();
}

我个人更喜欢将控件的行为逻辑放在控件的代码中。我的意思是扩展标准控件,以便按照我需要的方式改变它们的行为。

首先我需要扩展ListViewItem控件:

namespace Sample
{
    public class ListViewItem : System.Windows.Controls.ListViewItem
    {
        protected override void OnSelected(RoutedEventArgs e)
        {
            base.OnSelected(e);
            if (IsSelected)
            {
                Focus();
            }
        }
    }
}

然后我需要一个ListView控件,使用我的ListViewItem:

namespace Sample
{
    public class ListView : System.Windows.Controls.ListView
    {
        protected override DependencyObject GetContainerForItemOverride()
        {
            return new ListViewItem();
        }
    }
}
所以我的XAML将变成:
<local:ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" ... />

我希望它能帮助你。