Search code examples
c#wpfmvvmtreeviewhierarchicaldatatemplate

WPF TreeView MVVM using HierarchicalDataTemplate is strange updating like same word


I want to show user's Folder (C:\Food\BBQ\Recipe\Recipefile.txt)

enter image description here

enter image description here

like that but result is ...

enter image description here

I make a project MVVM patteron wpf Using ViewModel.cs and View with HierarchicalDataTemplate

this is my codes

window1.xaml

<Window.Resources>
    <ObjectDataProvider x:Key="ObjectDataProviderKey">
        <ObjectDataProvider.ObjectInstance>
            <vm:FolderViewModel  FullPath="C:\Food"/>
        </ObjectDataProvider.ObjectInstance>
    </ObjectDataProvider>
    <HierarchicalDataTemplate
        DataType="{x:Type vm:FolderViewModel}"
        ItemsSource="{Binding Path=SubFolderCollection}">
        <TextBlock Text="{Binding Path=Name}" />
    </HierarchicalDataTemplate>


<TreeView Name="folderTreeView" Grid.ColumnSpan="2" Grid.Row="2">
        <TreeViewItem
            Header="Favorit"
            ItemsSource="{Binding Source={StaticResource ObjectDataProviderKey}, Path=SubFolderCollection}" />
    </TreeView>

and viewModel FolderViewModel.cs

 namespace TEST.ViewModels.TreeView
{
    public class FolderViewModel : INotifyPropertyChanging
    {
        namespace TEST.ViewModels.TreeView
        {
        public class FolderViewModel : INotifyPropertyChanging
        {
            #region Field


            private DirectoryInfo directoryInfo;
            private ObservableCollection<FolderViewModel> subFolderCollection;


            private ObservableCollection<FileInfo> fileInfoCollection;

            #endregion


            #region  - FullPath


            public string FullPath
            {
                get
                {
                    return directoryInfo.FullName;
                }

                set
                {
                    if (Directory.Exists(value))
                    {
                        directoryInfo = new DirectoryInfo(value);
                    }
                    else
                    {
                        throw new ArgumentException("No exist.", "FullPath");
                    }
                }
            }

            #endregion
            #region  - Name


            private string _Name = string.Empty;

            public event PropertyChangingEventHandler PropertyChanging;

            public string Name
            {
                get
                {
                    _Name = directoryInfo.Name;
                    return _Name;
                }

                set
                {
                    _Name = value;
                    OnpropertyChanaged("Name");
                }
            }

            private void OnpropertyChanaged(string v)
            {
                throw new NotImplementedException();
            }



            #endregion
            #region  - SubFolderCollection


            public ObservableCollection<FolderViewModel> SubFolderCollection
            {
                get
                {
                    if (subFolderCollection == null)
                    {
                        subFolderCollection = new ObservableCollection<FolderViewModel>();

                        DirectoryInfo[] directoryInfoArray = directoryInfo.GetDirectories();

                        //DirectoryInfo[] directoryInfoArray = (DirectoryInfo[])this.directoryInfo.GetFileSystemInfos();
                        for (int i = 0; i < directoryInfoArray.Length; i++)
                        {
                            FolderViewModel folder = new FolderViewModel();
                            FullPath = directoryInfoArray[i].FullName;

                            this.subFolderCollection.Add(folder);
                        }
                    }

                    return subFolderCollection;
                }
            } 
            #endregion
            #region  FileInfoCollection


            public ObservableCollection<FileInfo> FileInfoCollection
            {
                get
                {
                    if (this.fileInfoCollection == null)
                    {
                        this.fileInfoCollection = new ObservableCollection<FileInfo>();

                        FileInfo[] fileInfoArray = this.directoryInfo.GetFiles();

                        for (int i = 0; i < fileInfoArray.Length; i++)
                        {
                            this.fileInfoCollection.Add(fileInfoArray[i]);
                        }
                    }

                    return this.fileInfoCollection;
                }
            }

            #endregion

            #region  - Folder()

            public FolderViewModel()
            {
                FullPath = @"C:\Food\";
            }

            #endregion
        }
    }

what should i do ??


Solution

  • If I understood you correctly. To Achieive the way you wanted you can do something like this.
    MainWindow.xaml

     <TreeView ItemsSource="{Binding TreeModel}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Child}">
                    <Grid>
                        <Label Content="{Binding Name}"/>
                    </Grid>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    

    And Then your ViewModel you can create a collection which goes through your folders and add folder and file name

    MainViewModel.cs

       public ObservableCollection<DirModel> TreeModel { get; set; }
       
        public MainViewModel()
        {
            TreeModel = new ObservableCollection<DirModel>();
            Load();
        }
    
        void Load()
        {
            var root = "C:\\TEST";
            foreach (var dirInfo in new DirectoryInfo(root).GetDirectories())
            {
                var dir = new DirModel() { Name = dirInfo.Name };
                foreach (var sb in dirInfo.GetDirectories())
                {
                    var sDir = new ChildDirModel() { Name = sb.Name };
                    var sFile = new FileModel() { Name = sb.GetFiles().First().Name };
                    sDir.Child.Add(sFile);
                    dir.Child.Add(sDir);
                }
                TreeModel.Add(dir);
            }
        }
    

    Finally create a Model class which represent your structure

    public class DirModel
    {
        public string Name { get; set; }
    
        public ObservableCollection<ChildDirModel> Child { get; set; }
    
        public DirModel()
        {
            Child = new ObservableCollection<ChildDirModel>();
        }
    }
    
    public class ChildDirModel
    {
        public string Name { get; set; }
    
        public ObservableCollection<FileModel> Child { get; set; }
    
        public ChildDirModel()
        {
            Child = new ObservableCollection<FileModel>();
        }
    }
    
    public class FileModel
    {
        public string Name { get; set; }
    }
    

    Your application will look like this

    enter image description here