c# - 自动选择添加到 ObservableCollection 的项目

标签 c# wpf listview mvvm observablecollection

我试图在将一个项目添加到 ObservableCollection 时自动选择 ListView 中的一个项目。我正在使用 CollectionChanged 事件来监听何时添加项目,然后选择它。 CollectionChanged 事件似乎发生在 UI 更新之前,因此相应地调整了 SelectedIndex。我尝试同时设置 SelectedIndex 和 SelectedItem,但在这两种情况下,添加的项目最终都被选中。正确的索引是当集合更改时,UI 更新,然后索引由 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>

和 View 模型:

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 事件处理程序中删除您的代码。如果 UI 尚未更新,您可能还需要调用 NotifyPropertyChanged("Items"); 来更新它。


更新>>>

然后尝试将其添加到您的 CollectionChanged 处理程序中:

if (e.Action == NotifyCollectionChangedAction.Add) 
    SelectedItem = e.NewItems[0] as string;

关于c# - 自动选择添加到 ObservableCollection 的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25672111/

相关文章:

android - 在 fragment 中滚动 ListView 时向上移动 View

c# - C# 中的 C++ API 和 PInvoke

c# - 动态数据显示分散的日期时间轴

java - Android TodoApp 与 ListView - 列表不显示

c# - 以编程方式将按钮添加到wpf中的工具栏

wpf - ReactiveUI 生产准备好了吗?

java - 不同 ListView 项的不同选择颜色

c# - 加快将 rtf 转换为纯文本的速度

c# - 为 Log4Net 中的特定异常设置日志记录级别(对于 Episerver)

c# - C# 中是否有带参数约束的泛型构造函数?