1

问题:让用户控件的“视图模型”(.xaml.cs 文件)知道 ListViewItem 已添加到 ListView 的“正确”方式是什么?请注意,这篇文章解决了一个不同的问题。

细节:

我有一个包含 ListView 和 DataContext 的 UserControl:

  1. ListView 有一个 ItemsSource={Binding ActionLogEntries}
  2. ActionLogEntries 是 DataContext 中的 ObservableCollection 属性

当某些事情发生时,数据上下文会将项目添加到 ListView。

但是没有 ListView.ItemAdded 事件。在数据上下文中的 ObservableCollection 上有一个 CollectionChanged 事件,但视图模型的该事件的处理程序可能会在项目添加到 ListView 之前被调用,因此这似乎不是一个好的策略。

仅供参考:这是因为当项目添加到 ListView 时,它不会自动滚动到新添加的项目,这是我必须添加的行为。大概我会在那之后使用 ScrollIntoView 。

4

1 回答 1

1

所以至少有两种方法可以给这只猫剥皮:

  1. 按照克莱门斯在评论我的问题时的解释
  2. 按照WPF Mentor的这篇文章做

解决方案 1 对于事件订阅来说似乎更自然,因为您不需要强制转换;IntelliSense 也不会在没有强制转换的情况下显示已实现接口的类成员,因此对于解决方案 2,您必须记住查看实现了哪些接口并检查那里的事件。以下是每个解决方案的订阅内容:

protected override void OnInitialized(EventArgs e)
{
    base.OnInitialized(e);

    // Solution 1, subscription:
    xActionListView.ItemContainerGenerator.ItemsChanged +=
        new ItemsChangedEventHandler(ActionLog_ItemsChanged);

    // Solution 2, subscription:
    ((INotifyCollectionChanged)xActionListView.Items).CollectionChanged += 
        new NotifyCollectionChangedEventHandler(ActionListView_CollectionChanged);
}

但是解决方案 2 在处理程序中更容易使用事件 arg:

// Solution 1, handler: 
private void ActionLog_ItemsChanged(object sender, ItemsChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        // Solution 1, scroll the new item into view  
        xActionListView.ScrollIntoView(
            xActionListView.Items[e.Position.Index + e.Position.Offset]);
    }      
}

// Solution 2, handler: 
private void ActionListView_CollectionChanged(
    object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        // Solution 2, scroll the new item into view  
        xActionListView.ScrollIntoView(e.NewItems[0]);
    }      
}

看起来在某些情况下,一种解决方案可能比另一种更合适:根据您需要的数据,事件数据可能更容易在其中一种或另一种中使用。

于 2013-02-16T14:07:29.617 回答