2010-12-03 3 views
1

Heirarchical DataTemplates 및 TreeViews에서 WPF로 머리를 쓰려고하는데 문제가 있습니다.WPF Heirachical DataTemplate in TreeView

다음과 같이 양식에 TreeView 만있는 응용 프로그램을 만들고 Directory 개체와 File 개체 모두에 대해 HierarchicalDataTemplate을 정의한 다음 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> 

이 내 디렉토리를 볼 수있는 트 리뷰에서 그 작동하고 재귀 적으로 모든 하위 디렉토리를 표시하지만 내가보고 싶은 것은 디렉토리 및 파일입니다! 모델을 확인한 결과 하위 디렉토리에 파일이 있지만 나무에서 볼 수는 없습니다.

내 템플릿이 문제인지 아니면 내 모델인지 확실하지 않아 모두 포함했습니다. :-)

감사

원샷

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 항목을 추가하는 것이 좋습니다.

정보를 저장하는 방법을 다시 생각하고 모든 것을 단일 컬렉션에 넣을 수 있습니다. 다른 목록은 기본 모음의 단순히 필터링 된보기입니다.

+0

건배 Dan, 나는 디렉토리와 파일 모두가 상속하고 사용하는 기본 유형의 2 차 관찰 가능 콜렉션을 채우라는 제안과 함께갔습니다! – OneSHOT