34

さまざまなサイズのアイテムで仮想化が有効になっている場合TreeView、複数の問題が発生します。

  • 垂直スクロールバーはサイズをランダムに変更し、ツリー全体を表示した後、要素のサイズを記憶しません。マウスでスクロールするのは難しいです。

  • 上下にスクロールするとArgumentNullException、フレームワークコードからスローされます。

再生成は簡単です。新しいWPFアプリケーションを作成し、このコードを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>

そしてこのコードを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; }
    }
}

アプリケーションが実行されたら、マウスカーソルをツリービューに移動し、マウスホイールを使用して下にスクロールし、次に上にスクロールしてから、もう一度下にスクロールし始めます。途中のどこかで、次の例外がスローされます。

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()

また、例外だけが問題ではないこともわかります。上下にスクロールすると、スクロールバーのサイズが常に変化します。(サイズを予測できないという同じ問題は発生しませんが、ListBoxリスト全体を表示した後の全高は記憶されます。)

質問:スクロールバーを正しく動作させて例外を取り除くにはどうすればよいですか?(代替のTreeViewコントロールへのリンクや、このシナリオをサポートする仮想化パネルへのリンクは気にしません。)

4

4 に答える 4

10

リンクをより目立たせるために、私も回答に投稿しています。フレームワークコード内にバグがあるようで、回避策はまだ見つかりません。MicrosoftConnectのバグを報告しました。

Microsoft Connect:仮想化されたWPFTreeViewでのスクロールは非常に不安定です

@sixlettervariablesによるコメントに投稿された多分関連するバグもあります:

Microsoft Connect:特定の条件下でTreeViewをスクロールしているときにWPFアプリケーションがフリーズする

バグを再現できる場合は、投票してください。

于 2013-06-05T07:54:27.937 に答える
2

.NET 5の時点で、この問題はWPFにまだ存在し、MicrosoftはMicrosoft Connectを廃止したため、これがもはや彼らのレーダーにあるかどうかは不明です。私は同じ問題に遭遇し、純粋に偶然に私のために働いた修正に出くわしました。基本的には、HierarchichalDataTemplateを使用して各ノードをレンダリングし、TreeViewが実行する必要があるのと同じことを実行しますが、組み込みのTreeViewがスクロール中にクラッシュする場合、このバージョンは(私の場合はアイテムのツリーでは)クラッシュしません。

<DockPanel>
   <DockPanel.Resources>
      <HierarchicalDataTemplate DataType="{x:Type src:Item}" ItemsSource="{Binding Path=Children}">
         <TextBlock Text"{Binding}"/>
      </HierarchicalDataTemplate>
   </DockPanel.Resources>

   <TreeView x:Name="tvwItems" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" ItemsSource="{Binding Items}">
   </TreeView>
</DockPanel>
于 2021-07-19T19:48:51.893 に答える
1

デフォルトでは、仮想化スタックパネルはピクセルレンダリングを使用して子要素をレンダリングし、リサイクルモードはUIで不要になったツリービューコンテナ内の各要素を破棄します。これにより、スクロールバーのサイズが自動的に変更されます。VirtualizationPanelピクセルレンダリング技術は、スクロールオプションも遅くします。VirtualizingPanel.ScrollUnit = "Item"に変更すると、問題が解決します。以下の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"
              VirtualizingPanel.ScrollUnit="Item"
              >
        <TreeView.ItemTemplate>
            <DataTemplate>
                <Border Height="{Binding Height}"
                        Width="{Binding Height}"
                        BorderThickness="1"
                        Background="DarkGray"
                        BorderBrush="DarkBlue" />
            </DataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</Grid>
</Window>
于 2013-06-04T08:35:08.943 に答える
0

ウィンドウの読み込み中にwpfアプリケーションで同じエラーが発生しました。Visual Studio 2017調査の結果、この投稿のようなものが見つかりました。興味深いWindowStyle要素であることに気付きました。

私の場合、wpfおよびwindows属性値のXAMLデザインウィンドウのエラーは

WindowStyle = "none"

値をに変更しましたがWindowStyle ="SingleBorderWindow"、このエラーはなくなりました

于 2018-11-22T09:05:25.810 に答える