由于绑定导致 selectedIndex 发生变化时,关注选中的 ListViewItem

Focus on selected ListViewItem when selectedIndex is changed due to binding

我有一个将 selectedIndex 绑定到 ViewModel 的列表视图。 当 ViewModel 更改 selectedIndex 时,列表视图会选择新项目,不幸的是它不会关注它,如果列表中存在很多项目,那么这对用户来说很烦人。

如何使用 XAML 或至少尊重 MVVM 来改变对 selectedItem 的关注。

<ListView ItemsSource="{Binding allTags}" ItemTemplate="{StaticResource listTemplate}" 
          SelectedIndex="{Binding selectedIndex}">
</ListView>

您可以使用附加行为来聚焦 TextBox:

public static class FocusExtension
{
    public static bool GetIsFocused(TextBox textBox)
    {
        return (bool)textBox.GetValue(IsFocusedProperty);
    }

    public static void SetIsFocused(TextBox textBox, bool value)
    {
        textBox.SetValue(IsFocusedProperty, value);
    }

    public static readonly DependencyProperty IsFocusedProperty =
        DependencyProperty.RegisterAttached("IsFocused", typeof(bool), typeof(FocusExtension),
            new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));

    private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        TextBox textBox = d as TextBox;
        if ((bool)e.NewValue)
        {
            textBox.Dispatcher.BeginInvoke(new Action(()=> 
            {
                Keyboard.Focus(textBox);
            }), DispatcherPriority.Background);
        }
    }
}

查看:

<Window.DataContext>
    <local:TestWindowViewModel></local:TestWindowViewModel>
</Window.DataContext>

<Window.Resources>
    <DataTemplate x:Key="template">
        <TextBox x:Name="listItemTextBox">
            <TextBox.Style>
                <Style TargetType="TextBox">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListViewItem}}" Value="True">
                            <Setter Property="local:FocusExtension.IsFocused" Value="True" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBox.Style>
        </TextBox>
    </DataTemplate>
</Window.Resources>

<StackPanel>
    <ListView ItemsSource="{Binding myList}" ItemTemplate="{StaticResource template}" SelectedIndex="{Binding SelectedIndex}"></ListView>
</StackPanel>

查看模型:

public class TestWindowViewModel : INotifyPropertyChanged
{
    public List<string> myList { get; set; }

    private int _selectedIndex;

    public int SelectedIndex
    {
        get { return _selectedIndex; }
        set { _selectedIndex = value; }
    }


    public TestWindowViewModel()
    {
        myList = new List<string> { "one", "two", "three" };
        SelectedIndex = 1;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}