2010-12-03 3 views
1

Я пытаюсь получить голову вокруг Heirarchical DataTemplates и TreeViews в WPF, и у меня проблемы.WPF Heirachical DataTemplate в TreeView

Я создал приложение только с TreeView в форме, как указано ниже, и определил HierarchicalDataTemplate как для объекта Directory, так и для объекта File I, затем привязываю TreeView к свойству каталогов (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 я вижу свои каталоги и рекурсивно отображает все подкаталоги, но то, что я хочу видеть это каталоги и файлы! Я проверил модель, и она определенно имеет файлы в некоторых подкаталогах, но я не вижу их в дереве.

Я не уверен, что это мой шаблон, который является проблемой или моей моделью, поэтому я включил их все! :-)

Благодаря

OneShot

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 и добавить к нему файлы Directory и File параллельно с добавлением в коллекцию Files and Directories.

В качестве альтернативы вы можете пересмотреть, как вы храните свою информацию и размещаете все в одной коллекции. Другие списки затем просто фильтруют представления основной коллекции.

+0

Cheers Dan, я пошел с вашим предложением заполнить вторичную наблюдаемую коллекцию базового типа, которую и каталог и файл теперь наследуют и используют это! – OneSHOT 2010-12-23 10:58:36

Смежные вопросы