2012-12-30 9 views
30

仮想化は、アイテムは様々なサイズを持つTreeViewで有効になっている場合は、複数の問題が表示されます。スクロールは非常に不安定である

  • 垂直スクロールバーがランダムにそのサイズを変更した後、要素のサイズを覚えていません木全体を見る。マウスでスクロールするのは難しいです。

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

Reproduciingは単純です: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; } 
    } 
} 
に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> 

と、このコードは、新しいWPFアプリケーションを作成し、その後にこのコードを置きます

アプリケーションが実行されると、マウスカーソルをツリービューに移動し、マウスホイールを使用して下にスクロールし、上部をスクロールして、再びスクロールダウンしてください。途中で次の例外がスローされます。

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コントロールやこのシナリオをサポートする仮想化パネルへのリンクは気にしないでください)

+0

.NET 4または4.5を使用していますか? – Sisyphe

+0

@Sisyphe .NET 4.5、Windows 7(Aeroテーマ)、VS 2012 – Athari

+0

@Athari同じボックス(32ビット)でテストしましたが、スクロールバーのサイズは常に同じです。 –

答えて

10

リンクをもっと目立つようにするには、私も回答に投稿しています。フレームワークコード内にバグがあり、まだ回避策が見つかっていないようです。あなたがバグを再現できる場合

Microsoft Connect: WPF application freezes while scrolling the TreeView under specific conditions

:@sixlettervariablesによってコメントで投稿されました多分関連のバグもあり

Microsoft Connect: Scrolling in virtualized WPF TreeView is very unstable

:私はマイクロソフトConnectのバグを報告しています、投票してください。

+0

問題はマイクロソフトによって閉じられていますか?すべてのアップデートは.Net4.5で解決されていますか? –

+0

@RohitVatsマイクロソフトでは、「アップデートの正確な性質と日付は未定です」というコメントを考慮して、修正プログラムを既に含むようには見えません。 – Athari

+3

これは.NET 4.5.2で修正されました。 – user704772

0

デフォルトでは、仮想化スタックパネルはピクセルレンダリングを使用して子要素をレンダリングし、リサイクルモードはツリービューコンテナ内の各要素を破棄します。 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> 
+2

TreeViewの仮想化は 'ScrollUnit = Item'モードでは無意味です。 *はアイテムと見なされます。この例では、サブ項目がないために機能します。 'ScrollUnit = Pixel'が導入される前は、TreeViewの仮想化は完全に不可能でした。 – Athari

関連する問題