Я пытаюсь автоматически выбрать элемент в 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="<- 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? В моей фактической программе элемент не добавляется в том же месте, в котором он отображается, поэтому невозможно установить выделенный элемент отдельно.
Лучше использовать свойство 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;