WPF ListView with ItemsSource:如何知道模型何时添加项

WPF ListView with ItemsSource:如何知道模型何时添加项,wpf,listview,itemssource,Wpf,Listview,Itemssource,问题:让用户控件的“视图模型”(.xaml.cs文件)知道ListViewItem已添加到ListView的“正确”方式是什么?请注意,is解决了一个不同的问题 详情: 我有一个UserControl,其中包含ListView和DataContext: ListView有一个ItemsSource={Binding ActionLogEntries} ActionLogEntries是DataContext中的ObservableCollection属性 当某些事情发生时,数据上下文会向List

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

详情:

我有一个UserControl,其中包含ListView和DataContext:

  • ListView有一个ItemsSource={Binding ActionLogEntries}
  • ActionLogEntries是DataContext中的ObservableCollection属性
  • 当某些事情发生时,数据上下文会向ListView添加项

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


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

    因此,至少有两种给这只猫剥皮的方法:

  • 按照克莱门斯在评论我的问题时所解释的去做
  • 解决方案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]);
        }      
    }
    

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

    因此,至少有两种给这只猫剥皮的方法:

  • 按照克莱门斯在评论我的问题时所解释的去做
  • 解决方案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]);
        }      
    }
    

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

    如何处理ListView的事件?也许还为时过早……这似乎奏效了。然而,事件arg有点奇怪:e.Position是一个位置生成器,具有Index和Offset属性,如果您对添加的最新元素感兴趣,则必须添加Index+Offset。更多细节如下。如何处理ListView的事件?也许还为时过早……这似乎奏效了。然而,事件arg有点奇怪:e.Position是一个位置生成器,具有Index和Offset属性,如果您对添加的最新元素感兴趣,则必须添加Index+Offset。更多详情见下文。