将未实现的ListViewItem置于视图中

时间:2017-02-15 14:07:17

标签: wpf listview scrollviewer

我有一个ListView,它在开头就是空的。然后我不断向ListView添加项目。在某些时候,所有项目都填满了整个可用空间,从那里我想将ListView滚动到刚刚添加的项目。

通常,可以通过调用ListViewItem.BringIntoViewListView.ScrollIntoView(ListViewItem)来完成此操作。

但是,ListView绑定到ListCollectionView,而Source的源是ViewModel项的ObservableCollection。所以,我正在将ViewModel项添加到该集合中。然后通过绑定创建视图项。

由于项目位于可见区域之外,因此不会立即创建ListViewItem,更不用说了。如果滚动视图靠近ListView的底部,ListViewItem将在不久之后创建并实现。 1
如果滚动视图位于ListView中间的某个位置,则它根本不起作用。

IsVirtualizing设置为false可以解决问题,因为无论如何都会创建并实现该项目。但这显然有一些性能下降。

所以,我正试图找到一种方法,以便创建和实现刚刚添加到集合中的项目,并最终可以进入视图。

是否有人知道如何处理此问题?

1 如果滚动视图关闭到底部,它基本上可以工作,但有一个奇怪的行为,似乎只有每个其他ListViewItem进入视图。

2 个答案:

答案 0 :(得分:1)

VirtualizationPanel有一个方法BringIndexIntoViewPublic,可以生成项目并使其可见。

以下是所有相关代码的示例。

public class ListView_ViewModel
{
  private CollectionViewSource _collectionViewSource;
  private ObservableCollection<ListViewItem_ViewModel> _listViewItemViewModels;
  private ListView _listView;

  private void AddItem()
  {
    var newListViewItemViewModel = new ListViewItem_ViewModel();
    _listViewItemViewModels.Add(newListViewItemViewModel);
    var indexOfNewItem = _collectionViewSource.View.Cast<ListViewItem_ViewModel>()
                           .ToList().IndexOf(newListViewItemViewModel);
    var virtualizingPanel = VisualTreeHelper.FindChild<VirtualizingPanel>(_listView);
    virtualizingPanel.BringIndexIntoViewPublic(indexOfNewItem);
  }
}

答案 1 :(得分:0)

根据您的问题很难说出确切的问题。但是,这可能是因为Equals函数的行为。考虑这个结构:

<DockPanel>
    <Button Name="addItem" Click="addItem_Click" Content="Add new and scroll" DockPanel.Dock="Bottom"/>
    <ListView Name="sv" ScrollViewer.VerticalScrollBarVisibility="Visible">
    </ListView> 
</DockPanel>

有一个按钮试图添加新项目并滚动到最后。

如果添加不同的项目,它将起作用:

private void addItem_Click(object sender, RoutedEventArgs e)
{
    if (sv.ItemsSource == null)
        sv.ItemsSource = new ObservableCollection<string>();

    string newitem = "new item" + (sv.Items.Count + 1).ToString();
    ((ObservableCollection<string>)sv.ItemsSource).Add(newitem);
    sv.ScrollIntoView(newitem);
}

请注意,字符串永远不会相等(请参阅(sv.Items.Count + 1).ToString()部分)。但是,这不起作用:

private void addItem_Click(object sender, RoutedEventArgs e)
{
    if (sv.ItemsSource == null)
        sv.ItemsSource = new ObservableCollection<string>();

    string newitem = "new item";
    ((ObservableCollection<string>)sv.ItemsSource).Add(newitem);
    sv.ScrollIntoView(newitem);
} 

因为Equals会返回第一个项目。