2011-06-20 15 views
23

thisまたはthis otherのようなファイルパスのコレクションからツリービューを作成する方法の例がいくつかあります。私はWPFのためのそのような例を見つけることができないようです。私は、私はWindowsフォームを統合し、それを動作させるために別のコントロールを使用することができますが、私はwpfのツリービューコントロールで同じことをすることができればいいと思う。私が構築したいツリービューは約50,000個のファイルで構成されていますので、何かにバインドする方が良いと思います。しかし、バインドする前に、文字列のリスト(文字列にはファイルのパスが含まれています)に基づいて構造を作成すると便利です。wpfのファイルパスのリストからツリービューを作成する

+1

コレクション全体を最初に設定する必要はありません。必要に応じてツリーコントロールのフェッチを行うことができます。私はこれに対してteleriksツリーコントロールを使用しました。 –

答えて

53

私は質問に興味を持って一緒に投げました。最初のパスとして、私はあなたが探しているものにかなり近いと思う。私は、怠惰な読み込みは適切かもしれないと思うが、約50,000のアイテムについて話す。とにかく、ここにはジョシュ・スミスのarticleに基づいたシンプルなバージョンがあります。私はここにすべてのコードを書いていますが、実際にはデータテンプレートを使って魔法が実行されます。我々が作業しているオブジェクトを表すために、いくつかのクラスを考えると

...

using System.Collections.Generic; 

namespace WpfTreeViewBinding.Model 
{ 
    public class Item 
    { 
     public string Name { get; set; } 
     public string Path { get; set; } 
    } 
} 

と...

namespace WpfTreeViewBinding.Model 
{ 
    public class FileItem : Item 
    { 

    } 
} 

と...

namespace WpfTreeViewBinding.Model 
{ 
    public class DirectoryItem : Item 
    { 
     public List<Item> Items { get; set; } 

     public DirectoryItem() 
     { 
      Items = new List<Item>(); 
     } 
    } 
} 

Iいくつかのディレクトリ/ファイルをロードする再帰的な方法を作成しました...

そこから
using System.Collections.Generic; 
using System.IO; 
using WpfTreeViewBinding.Model; 

namespace WpfTreeViewBinding 
{ 
    public class ItemProvider 
    { 
     public List<Item> GetItems(string path) 
     { 
      var items = new List<Item>(); 

      var dirInfo = new DirectoryInfo(path); 

      foreach(var directory in dirInfo.GetDirectories()) 
      { 
       var item = new DirectoryItem 
           { 
            Name = directory.Name, 
            Path = directory.FullName, 
            Items = GetItems(directory.FullName) 
           }; 

       items.Add(item); 
      } 

      foreach(var file in dirInfo.GetFiles()) 
      { 
       var item = new FileItem 
           { 
            Name = file.Name, 
            Path = file.FullName 
           }; 

       items.Add(item); 
      } 

      return items; 
     } 
    } 
} 

それがデータを取得するだけです...

using System.Windows; 

namespace WpfTreeViewBinding 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      var itemProvider = new ItemProvider(); 

      var items = itemProvider.GetItems("C:\\Temp"); 

      DataContext = items; 
     } 
    } 
} 

そして、それを表示する...

<Window x:Class="WpfTreeViewBinding.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:Model="clr-namespace:WpfTreeViewBinding.Model" 
     Title="MainWindow" 
     Height="350" Width="525"> 

    <Window.Resources> 

     <HierarchicalDataTemplate DataType="{x:Type Model:DirectoryItem}" 
            ItemsSource="{Binding Items}"> 
      <TextBlock Text="{Binding Path=Name}" ToolTip="{Binding Path=Path}" /> 
     </HierarchicalDataTemplate> 

     <DataTemplate DataType="{x:Type Model:FileItem}"> 
      <TextBlock Text="{Binding Path=Name}" ToolTip="{Binding Path=Path}" /> 
     </DataTemplate> 

    </Window.Resources> 

    <Grid Margin="8"> 
     <TreeView ItemsSource="{Binding}" /> 
    </Grid> 

</Window> 

魔法のすべてが本当にデータテンプレートで発生します。私はすべてのことの鍵は、階層(すなわちディレクトリ)を持つすべての項目にHierarchicalDataTemplateを使用していると思います。

注1:これは広範にテストされていません。パフォーマンスのためにプロファイリングされていません。これは私がずっと前に解決しようとした問題なので、どんなフィードバックも歓迎します。ありがとう!

注記2:ハードコーディングされたパスは、システムで意味のあるものに設定する必要があります。ここで

は、以前のソリューションのための小型の拡張

enter image description here

+0

Jhonありがとう!あなたの答えはすばらしく見える。私は明日の朝に戻ってくるときあなたのソリューションをテストすることを楽しみにしています。それ以上編集しないでください...まずそれをテストしてみましょう。 –

+4

これは良い答えです。ただし、ItemおよびFileItemクラスを作成する必要はありません。両方のシステム用にローカルのDataTemplateを作成することができます。IO DirectoryInfoクラスとFileInfoクラス。 –

+0

遅延ロードを使用するように強化する]] – cordialgerm

3

...さまざまなレベルでディレクトリとファイルを示すスクリーンショットである: 私は、XAMLのアイコンをサポートするためのコード、およびのアイコンを切り替えるためのサポートを追加しました開いたフォルダと閉じたフォルダ:

<HierarchicalDataTemplate DataType="{x:Type viewModels:SourceControlDirecoryViewModel}" 
            ItemsSource="{Binding Items}"> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="Auto" /> 
        <ColumnDefinition Width="5" /> 
        <ColumnDefinition Width="*" /> 
       </Grid.ColumnDefinitions> 
       <Image Width="16" 
         Height="16" 
         Source="{StaticResource ImageSourceFolderClosed16x16}" 
         x:Name="img" /> 
       <TextBlock Text="{Binding Path=Name}" 
          ToolTip="{Binding Path=Path}" 
          Grid.Column="2" /> 
      </Grid> 
      <DataTemplate.Triggers> 
       <DataTrigger Binding="{Binding IsExpanded, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TreeViewItem}}}" 
          Value="True"> 
        <Setter Property="Source" 
          TargetName="img" 
          Value="{StaticResource ImageSourceFolderOpened16x16}" /> 
       </DataTrigger> 
      </DataTemplate.Triggers> 
     </HierarchicalDataTemplate> 
関連する問題