2010-12-03 99 views
1

我想讓我的頭在WPF中的Heirarchical DataTemplates和TreeViews中,並遇到一些麻煩。WPF在TreeView中的Heirachical DataTemplate

我已經在窗體上創建了一個只有TreeView的應用程序,併爲Directory對象和File對象定義了HierarchicalDataTemplate,然後將TreeView綁定到我的模型的Directories屬性(ObservableCollection)。

<Grid> 
     <Grid.Resources> 

      <HierarchicalDataTemplate DataType="{x:Type local:Directory}" ItemsSource ="{Binding Directories}"> 
       <TextBlock Text="{Binding Path=Name}"/> 
      </HierarchicalDataTemplate> 
      <HierarchicalDataTemplate DataType="{x:Type local:File}" ItemsSource ="{Binding Files}"> 
       <TextBlock Text="{Binding Path=FileName}"/> 
      </HierarchicalDataTemplate> 
     </Grid.Resources> 
     <TreeView Margin="12,12,0,12" Name="treeView1" HorizontalAlignment="Left" Width="204" > 
      <TreeViewItem ItemsSource="{Binding Directories}" Header="Folder Structure" /> 
     </TreeView> 
    </Grid> 

這工作,因爲在TreeView我看到我的目錄和它遞歸地顯示所有子目錄,但我想看到的是目錄和文件!我已經檢查過模型,並且它在一些子目錄中肯定有文件,但我無法在樹中看到它們。

我不確定是我的模板是問題還是我的模型,所以我將它們都包含在內! :-)

感謝

單次

public partial class MainWindow : Window 
{ 

    public MainWindow() 
    { 
     InitializeComponent(); 

    } 


    private MainWindowViewModel _vm; 

    public MainWindowViewModel VM 
    { 
     set 
     { 
      _vm = value; 
      this.DataContext = _vm; 
     } 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     var d = new Directory() { Name = "temp" }; 
     recurseDir("c:\\temp", ref d); 

     VM = new MainWindowViewModel(new List<Directory>() { d });    
    } 

    private void recurseDir(string path, ref Directory dir) 
    { 
     var files = System.IO.Directory.GetFiles(path); 
     var dirs = System.IO.Directory.GetDirectories(path); 

     dir.Name = path.Substring(path.LastIndexOf("\\")+1); 

     for (int i = 0; i < files.Length; i++) 
     { 
      var fi = new FileInfo(files[i]); 
      dir.Files.Add(new File() { 
       FileName = System.IO.Path.GetFileName(files[i]), 
       DirectoryPath = System.IO.Path.GetDirectoryName(files[i]), 
       Size = fi.Length, 
       Extension= System.IO.Path.GetExtension(files[i]) 
      }); 

     } 

     for (int i = 0; i < dirs.Length; i++) 
     { 
      var d = new Directory() { Name = dirs[i].Substring(dirs[i].LastIndexOf("\\")+1) }; 
      recurseDir(dirs[i], ref d); 
      dir.Directories.Add(d); 

     } 

    } 
} 

-

public class MainWindowViewModel 
     : DependencyObject 
    { 


     public MainWindowViewModel(List<Directory> Dirs) 
     { 
      this.Directories = new ObservableCollection<Directory>(Dirs); 
     } 

     public ObservableCollection<Directory> Directories 
     { 
      get { return (ObservableCollection<Directory>)GetValue(DirectoriesProperty); } 
      set { SetValue(DirectoriesProperty, value); } 
     } 

     public static readonly DependencyProperty DirectoriesProperty = 
      DependencyProperty.Register("Directories", typeof(ObservableCollection<Directory>), typeof(MainWindowViewModel), new UIPropertyMetadata(null)); 

     public Directory BaseDir 
     { 
      get { return (Directory)GetValue(BaseDirProperty); } 
      set { SetValue(BaseDirProperty, value); } 
     } 

     public static readonly DependencyProperty BaseDirProperty = 
      DependencyProperty.Register("BaseDir", typeof(Directory), typeof(MainWindowViewModel), new UIPropertyMetadata(null)); 


    } 

-

public class Directory 
    { 
     public Directory() 
     { 
      Files = new List<File>(); 
      Directories = new List<Directory>(); 
     } 
     public List<File> Files { get; private set; } 
     public List<Directory> Directories { get; private set; } 
     public string Name { get; set; } 
     public int FileCount 
     { 
      get 
      { 
       return Files.Count; 
      } 
     } 
     public int DirectoryCount 
     { 
      get 
      { 
       return Directories.Count; 
      } 
     } 
     public override string ToString() 
     { 
      return Name; 
     } 
    } 

-

public class File 
    { 
     public string DirectoryPath { get; set; } 
     public string FileName { get; set; } 
     public string Extension { get; set; } 
     public double Size { get; set; } 
     public string FullPath 
     { 
      get 
      { 
       return System.IO.Path.Combine(DirectoryPath, FileName); 
      } 
     } 
     public override string ToString() 
     { 
      return FileName; 
     } 
    } 

回答

2

再看看這個:

 <HierarchicalDataTemplate DataType="{x:Type local:Directory}" ItemsSource ="{Binding Directories}"> 
      <TextBlock Text="{Binding Path=Name}"/> 
     </HierarchicalDataTemplate> 
     <HierarchicalDataTemplate DataType="{x:Type local:File}" ItemsSource ="{Binding Files}"> 
      <TextBlock Text="{Binding Path=FileName}"/> 
     </HierarchicalDataTemplate> 

什麼你說的是,如果你遇到File類型的對象,與文本塊顯示,並從下一個屬性Files得到它的孩子File。你真正想要的是什麼文件到每個目錄下出現,所以你應該創建一個公開兩種目錄和文件的新屬性:

public class Directory 
{ 
    //... 
    public IEnumerable<Object> Members 
    { 
     get 
     { 
      foreach (var directory in Directories) 
       yield return directory; 

      foreach (var file in Files) 
       yield return file; 
     } 
    } 
    //... 
} 

,然後你的模板變爲:

<HierarchicalDataTemplate DataType="{x:Type local:Directory}" ItemsSource ="{Binding Members}"> 
     <TextBlock Text="{Binding Path=Name}"/> 
    </HierarchicalDataTemplate> 
    <DataTemplate DataType="{x:Type local:File}"> 
     <TextBlock Text="{Binding Path=FileName}"/> 
    </DataTemplate> 

更新:

其實,以上是不夠的,如果你想收到會員收集變更通知。如果是這種情況,我建議創建一個新的ObservableCollection,並將目錄和文件條目並行添加到文件和目錄集合中。

或者,您可能希望重新考慮如何存儲信息並將所有內容都放在一個集合中。其他列表則是主集合的簡單過濾視圖。

+0

乾杯丹,我與你的建議填充一個基本類型的輔助可觀察集合,目錄和文件現在繼承和使用它! – OneSHOT 2010-12-23 10:58:36