滚动虚拟化WPF TreeView的是非常不稳定 [英] Scrolling in virtualized WPF TreeView is very unstable

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

问题描述

如果虚拟化已启用的的TreeView 与具有不同尺寸的物品,许多问题出现:

If virtualizing is enabled in TreeView with items having various sizes, multiple problems appear:

  • 垂直滚动条随机改变它的大小和观看整棵树后不记得元素的大小。用鼠标滚动是很难的。

  • Vertical scroll bar changes its size randomly and doesn't remember sizes of elements after viewing the whole tree. Scrolling with mouse is hard.

在一些上下滚动, ArgumentNullException 从框架code抛出。

After some scrolling up and down, ArgumentNullException is thrown from the framework code.

Reproduciing很简单:创建一个新的WPF应用程序,然后把这个code到 MainWindow.xaml

Reproduciing is simple: create a new WPF application, then put this code into MainWindow.xaml

<Window x:Class="VirtualTreeView.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="800" Width="400" Left="0" Top="0"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <TreeView x:Name="tvwItems" ItemsSource="{Binding Items}"
                VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling">
            <TreeView.ItemTemplate>
                <DataTemplate>
                    <Border Height="{Binding Height}" Width="{Binding Height}"
                            BorderThickness="1" Background="DarkGray" BorderBrush="DarkBlue"/>
                </DataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
</Window>

这code到 MainWindow.xaml.cs

using System.Collections.ObjectModel;
using System.Linq;

namespace VirtualTreeView
{
    public partial class MainWindow
    {
        public ObservableCollection<Item> Items { get; set; }

        public MainWindow ()
        {
            Items = new ObservableCollection<Item>(Enumerable.Range(0, 20).Select(i => new Item {
                Height = i*20,
            }));
            InitializeComponent();
        }
    }

    public class Item
    {
        public double Height { get; set; }
    }
}

当应用程序被运行,将鼠标光标移动到一个TreeView,使用鼠标滚轮滚动至底部,然后滚动到顶部,然后开始向下滚动再次。在中间某个地方下抛出异常:

When application is ran, move mouse cursor into a treeview, scroll to the bottom using mouse wheel, then scroll to the top, then start scrolling down again. Somewhere in the middle the following exception is thrown:

System.ArgumentNullException was unhandled
  HResult=-2147467261
  Message=Value cannot be null.
Parameter name: element
  Source=PresentationCore
  ParamName=element
  StackTrace:
       at MS.Internal.Media.VisualTreeUtils.AsNonNullVisual(DependencyObject element, Visual& visual, Visual3D& visual3D)
       at System.Windows.Media.VisualTreeHelper.GetParent(DependencyObject reference)
       at System.Windows.Controls.VirtualizingStackPanel.FindScrollOffset(Visual v)
       at System.Windows.Controls.VirtualizingStackPanel.OnAnchorOperation(Boolean isAnchorOperationPending)
       at System.Windows.Controls.VirtualizingStackPanel.OnAnchorOperation()
       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
       at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
       at System.Windows.Threading.DispatcherOperation.InvokeImpl()
       at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Windows.Threading.DispatcherOperation.Invoke()
       at System.Windows.Threading.Dispatcher.ProcessQueue()
       at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
       at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
       at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
       at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
       at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
       at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
       at System.Windows.Threading.Dispatcher.Run()
       at System.Windows.Application.RunDispatcher(Object ignore)
       at System.Windows.Application.RunInternal(Window window)
       at System.Windows.Application.Run(Window window)
       at System.Windows.Application.Run()
       at VirtualTreeView.App.Main() in d:\Docs\Projects\_Try\VirtualTreeView\obj\Debug\App.g.cs:line 0
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()

您也可以看到,例外是不是唯一的问题。当上下滚动,滚动条,不断地改变它的大小。 (同样的问题不会出现在列表框哪些不能predict大小,但查看完整列表之后记得总高度。)

You can also see that exception is not the only problem. When scrolling up and down, scroll bar constantly changes its size. (The same problem doesn't appear in ListBox which can't predict size, but remembers total height after viewing the whole list.)

问:如何使滚动条举止得体,摆脱了异常? (我不介意链接替代的TreeView控件或者虚拟化的面板,支持此方案。)

Question: How to make the scroll bar behave properly and get rid of the exception? (I don't mind links to alternative TreeView controls or maybe virtualizing panels which support this scenario.)

推荐答案

为了使链接更加突出,我张贴的答案了。它看起来像一个bug是在框架code,也没有发现尚未解决方法。我报告了Microsoft Connect上的错误:

To make the link more prominent, I am posting it in an answer too. It looks like a bug is within the framework code and there are no workarounds found yet. I have reported the bug on Microsoft Connect:

<一个href="https://connect.microsoft.com/VisualStudio/feedback/details/789438/scrolling-in-virtualized-wpf-treeview-is-very-unstable">Microsoft连接:滚动在虚拟化的WPF TreeView的是非常不稳定

还有这是由@sixlettervariables张贴在评论一个可能与错误:

There is also a maybe related bug which was posted in the comments by @sixlettervariables:

<一个href="http://connect.microsoft.com/VisualStudio/feedback/details/763639/wpf-application-built-on-net-4-0-freezes-under-system-with-net-4-5-while-scrolling-the-treeview-under-specific-conditions">Microsoft连接:WPF应用程序冻结,同时滚动特定条件下的树视图

如果你能重现错误,请投他们。

If you can reproduce the bugs, please vote them up.

这篇关于滚动虚拟化WPF TreeView的是非常不稳定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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