Ciprian Dragoe
Ciprian Dragoe

Reputation: 339

Focus on selected ListViewItem when selectedIndex is changed due to binding

I have a listview that has the selectedIndex binded to the ViewModel. When the ViewModel changes the selectedIndex the listview selects the new item, unfortunately it does not focus on it and if a lot items are present in the list then this is annoying for the user.

How can I change to focus to the selectedItem using XAML or at least respecting MVVM.

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

Upvotes: 0

Views: 662

Answers (1)

mm8
mm8

Reputation: 169200

You could use an attached behaviour to focus the 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);
        }
    }
}

View:

<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>

View Model:

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

Upvotes: 1

Related Questions