具有ListBox的WPF ListBox-UI虚拟化和滚动 [英] WPF ListBox with a ListBox - UI Virtualization and Scrolling

查看:132
本文介绍了具有ListBox的WPF ListBox-UI虚拟化和滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的原型显示包含页面"的文档" 用缩略图表示.每个文件可以有 任何数量的页面.例如,可能有 1000个文档(每页5页)或5个文档(每页1000页) 每个,或介于两者之间的某个位置.文件不包含其他文件. 在我的xaml标记中,我有一个ListBox,其ItemsTemplate 引用一个也具有ListBox的innerItemsTemplate.我想要 2级所选项目,以便我可以执行各种操作 在文档或页面上(删除,合并,移动到新位置等). innerItemsTemplate ListBox使用WrapPanel作为ItemsPanelTemplate.

My prototype displays "documents" that contain "pages" that are represented by thumbnail images. Each document can have any number of pages. For example, there might be 1000 documents with 5 pages each, or 5 documents with 1000 pages each, or somewhere inbetween. Documents do not contain other documents. In my xaml markup I have a ListBox, whose ItemsTemplate references an innerItemsTemplate that also has a ListBox. I want the 2 levels of selected items so that I can perform various operations on documents or pages (delete, merge, move to new location, etc). The innerItemsTemplate ListBox uses a WrapPanel as the ItemsPanelTemplate.

对于这种情况,我有大量的文档,但有一些文档 每页(例如10000个文档,每页5页),滚动 VirtualizingStackPanel的UI虚拟化使它的工作非常出色. 但是,如果我有大量页面,则会遇到问题.一个文件 具有1000页的页面一次只能显示50张(无论屏幕大小如何),当我向下滚动时,外部ListBox会移至下一个文档,而跳过950 页面或不可见的页面.除此之外,没有 VirtualzingWrapPanel因此应用程序的内存确实增加了.

For the scenario where I have a large number of documents with a few pages each (say, 10000 documents with 5 pages each), the scrolling works great thanks to the UI Virtualization by the VirtualizingStackPanel. However, I have problems if I have a large number of pages. A document with 1000 pages will only display about 50 at a time (whatever fits on the screen), and when I scroll down, the outer ListBox moves to the next document, skipping the 950 pages or so that were not visible. Along with that, there is no VirtualzingWrapPanel so the app memory really increases.

我想知道我是否正在正确地做这件事,尤其是 因为有点难以解释!我希望能够显示 10000个文档,每个文档1000页(仅显示屏幕上适合的所有内容), 使用UI虚拟化,还可以平滑滚动.

I'm wondering if I am going about this the right way, especially since it is sort of difficult to explain! I would like to be able to display 10000 documents with 1000 pages each (only showing whatever fits on the screen), using UI Virtualization, and also smooth scrolling.

如何确保滚动浏览文档中的所有页面 在显示下一个文档之前,仍然保持UI虚拟化吗? 滚动条似乎仅移至下一个文档.

How can I make sure the scrolling moves through all of the pages in document before it displays the next document, and still keep UI virtualization? The scrollbar seems to only move to the next document.

代表文档"和页面"似乎合乎逻辑吗? 我目前在ListBox中使用ListBox的方法?

Does it seem logical to represent "documents" and "pages" - with my current method of using a ListBox within a ListBox?

我非常感谢您有任何想法. 谢谢.

I would very much appreciate any ideas you have. Thank You.

推荐答案

这里的答案令人惊讶:

  • 如果使用ItemsControlListBox,您将获得所遇到的行为,其中控件滚动按项目",因此您可以一次跳过整个文档,但
  • 如果您改用TreeView,则控件将平滑滚动,因此您可以滚动浏览文档并进入下一个文档,但仍可以进行虚拟化.
  • If you use ItemsControl or ListBox you will get the behavior you are experiencing, where the control scrolls "by item" so you jump over a whole document at once, BUT
  • If you use TreeView instead, the control will scroll smoothly so you can scroll through your document and into the next one, but it will still be able to virtualize.

我认为WPF团队选择此行为的原因是TreeView通常具有大于可见区域的项目,而通常ListBox则没有.

I think the reason the WPF team chose this behavior is that TreeViewcommonly has items that are larger than the visible area, whereas typically ListBoxes don't.

在任何情况下,在WPF中通过简单地修改ItemContainerStyle来使TreeView外观和行为类似于ListBoxItemsControl都是微不足道的.这很简单.您可以自己滚动,也可以只复制系统主题文件中的相应模板.

In any case, it is trivial in WPF to make a TreeView look and act like a ListBox or ItemsControl by simply modifying the ItemContainerStyle. This is very straightforward. You can roll your own or just copy over the appropriate template from the system theme file.

所以您将遇到类似这样的情况:

So you will have something like this:

<TreeView ItemsSource="{Binding documents}">
  <TreeView.ItemsPanel>
    <ItemsPanelTemplate>
      <VirtualizingStackPanel />
    </ItemsPanelTemplate>
  </TreeView.ItemsPanel>
  <TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type TreeViewItem}">
            <ContentPresenter /> <!-- put your desired container style here  with a ContentPresenter inside -->
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </TreeView.ItemContainerStyle>
  <TreeView.ItemTemplate>
    <DataTemplate TargetType="{x:Type my:Document}">
      <Border BorderThickness="2"> <!-- your document frame will be more complicated than this -->
        <ItemsControl ItemsSource="{Binding pages}">
          ...
        </ItemsControl>
      </Border>
    </DataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

使基于像素的滚动和ListBox样式的多选功能协同工作

如果使用此技术进行基于像素的滚动,则显示文档的外部ItemsControl不能是ListBox(因为ListBox不是TreeView或TreeViewItem的子类).因此,您将失去所有ListBox的多选支持.据我所知,如果不为一个功能或另一个功能添加一些自己的代码,就无法将这两个功能一起使用.

If you use this technique to get pixel-based scrolling, your outer ItemsControl which shows the documents cannot be a ListBox (because ListBox is not a subclass of TreeView or TreeViewItem). Thus you lose all of ListBox's multiselect support. As far as I can tell, there is no way to use these two features together without including some of your own code for one feature or the other.

如果在同一控件中需要两组功能,则基本上有几种选择:

If you need both sets of functionality in the same control, you have basically several options:

  1. 在TreeViewItem的子类中自己进行多重选择.使用TreeViewItem代替TreeView作为外部控件,因为它允许选择多个子级.在ItemsContainerStyle内的模板中:在ContentPresenter周围添加一个CheckBox,将模板绑定到IsSelected,并使用控件模板对CheckBox进行样式设置以获得所需的外观.然后添加您自己的鼠标事件处理程序,以处理Ctrl-Click和Shift-Click的多项选择.

  1. Implement multi-selection yourself in a subclass of TreeViewItem. Use TreeViewItem instead of TreeView for the outer control, since it allows multiple children to be selected. In the template inside ItemsContainerStyle: Add a CheckBox around the ContentPresenter, template bind the CheckBox to IsSelected, and style the CheckBox with control template to get the look you want. Then add your own mouse event handlers to handle Ctrl-Click and Shift-Click for multiselect.

在VirtualizingPanel的子类中自己实现像素滚动虚拟化.这相对简单,因为VirtualizingStackPanel的大部分复杂性与非像素滚动和容器回收有关. Dan Crevier的博客对于理解VirtualizingPanel具有一些有用的信息. p>

Implement pixel-scrolled virtualization yourself in a subclass of VirtualizingPanel. This is relatively simple, since most of VirtualizingStackPanel's complexity is related to non-pixel scrolling and container recycling. Dan Crevier's Blog has some useful infromation for understanding VirtualizingPanel.

这篇关于具有ListBox的WPF ListBox-UI虚拟化和滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆