2010-12-03 89 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