【问题标题】:WPF ListView with ItemsSource: how to know when model adds itemWPF ListView with ItemsSource:如何知道模型何时添加项目
【发布时间】:2013-01-31 19:43:00
【问题描述】:

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

详情:

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

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

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

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

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

【问题讨论】:

  • ListView的ItemContainerGeneratorItemsChanged事件怎么处理?也许还为时过早...
  • 这似乎有效。但是,事件 arg 有点奇怪:e.Position 是一个位置生成器,具有 Index 和 Offset 属性,如果您对最新添加的元素感兴趣,您似乎必须添加 index+offset。更多详情如下。

标签: wpf listview itemssource


【解决方案1】:

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

  1. 按照 Clemens 在对我的问题的评论中解释的方式进行操作
  2. this post by 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]);
    }      
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 2023-03-13
    相关资源
    最近更新 更多