Автоматически выбирать элемент, добавленный в коллекцию ObservableCollection

1

Я пытаюсь автоматически выбрать элемент в ListView всякий раз, когда он добавляется в ObservableCollection. Я использую событие CollectionChanged для прослушивания, когда элемент добавлен, а затем выберите его. Событие CollectionChanged, похоже, происходит до того, как пользовательский интерфейс будет обновлен, и поэтому SelectedIndex будет соответствующим образом скорректирован. Я попытался установить как SelectedIndex, так и SelectedItem, но в обоих случаях элемент после добавления добавляется. Правильный индекс - это когда коллекция изменяется, обновляется пользовательский интерфейс, а затем индекс увеличивается с помощью ListView.

Это явление можно продемонстрировать следующим образом:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" DataContext="{Binding Main, Source= {StaticResource Locator}}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <ListView ItemsSource="{Binding Items, Mode=TwoWay}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}" Grid.Row="0">
        </ListView>
        <StackPanel Orientation="Horizontal" Grid.Row="1">
            <Button Content="Add Item" Width="75" Command="{Binding AddItemCommand}"/>
            <Label Content="SelectedIndex:"/>
            <Label Content="{Binding SelectedIndex}"/>
            <Label Content="SelectedItem:"/>
            <Label Content="{Binding SelectedItem}"/>
            <Label Content="&lt;- Numbers should match after item added"/>
        </StackPanel>
    </Grid>
</Window>

и ViewModel:

public class MainViewModel : ViewModelBase
{
    private ICommand addItemCommand;
    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public MainViewModel()
    {
        Items = new ObservableCollection<string>();
        Items.CollectionChanged += Items_CollectionChanged;
    }

    private int selectedIndex = -1;
    public const string SelectedIndexPropertyName = "SelectedIndex";
    public int SelectedIndex
    {
        get
        {
            return selectedIndex;
        }
        set
        {
            if (selectedIndex != value)
            {
                selectedIndex = value;
                RaisePropertyChanged(SelectedIndexPropertyName);
            }
        }
    }

    private string selectedItem = null;
    public const string SelectedItemPropertyName = "SelectedItem";
    public string SelectedItem
    {
        get
        {
            return selectedItem;
        }
        set
        {
            if (selectedItem != value)
            {
                selectedItem = value;
                RaisePropertyChanged(SelectedItemPropertyName);
            }
        }
    }

    private ObservableCollection<string> items;
    public const string ItemsPropertyName = "Items";
    public ObservableCollection<string> Items
    {
        get
        {
            return items;
        }
        set
        {
            items = value;
            RaisePropertyChanged(ItemsPropertyName);
        }
    }

    private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
        {
            //SelectedItem = e.NewItems[0];
            SelectedIndex = e.NewStartingIndex;
        }
    }

    public ICommand AddItemCommand
    {
        get
        {
            if (addItemCommand == null)
                addItemCommand = new RelayCommand(() => Items.Add("Item " + items.Count));

            return addItemCommand;
        }
    }
}

Я добавил загруженное примерное решение на www.itzalive.co.uk/AddItemSelection.zip

Кто-нибудь знает, как в итоге добавить новый элемент, выбранный с помощью события CollectionChanged? В моей фактической программе элемент не добавляется в том же месте, в котором он отображается, поэтому невозможно установить выделенный элемент отдельно.

  • 0
    Где находится ваше свойство SelectedItem в C #?
  • 0
    Не включил его, поскольку он не использовался, по сути, он выглядит так же, как свойство SelectedIndex
Показать ещё 3 комментария
Теги:
wpf
observablecollection
mvvm
listview

1 ответ

5
Лучший ответ

Лучше использовать свойство SelectedItem, а не свойство SelectedIndex:

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

Затем в коде:

YourClass newItem = new YourClass();
Items.Add(newItem);
SelectedItem = newItem;

Также удалите свой код из Items_CollectionChanged событий Items_CollectionChanged. Вам также может потребоваться вызвать NotifyPropertyChanged("Items"); чтобы обновить пользовательский интерфейс, если он этого еще не сделал.


ОБНОВЛЕНИЕ >>>

Попробуйте добавить это в свой обработчик CollectionChanged:

if (e.Action == NotifyCollectionChangedAction.Add) 
    SelectedItem = e.NewItems[0] as string;
  • 0
    Я пытаюсь быть в состоянии сделать это так, чтобы элемент мог быть добавлен в список в любом месте, и он будет выбран. Это означает, что я не могу выбрать элемент в следующей строке, куда я его добавляю.
  • 0
    Я также ранее пробовал это, однако я получаю тот же результат. Кажется, что событие CollectionChanged происходит, когда данные и пользовательский интерфейс не синхронизированы, и поэтому происходят некоторые странные обновления.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню