简体   繁体   English

带有 HierarchicalDataTemplate 和 ObservableCollection 的 WPF TreeView 包含 Children

[英]WPF TreeView with HierarchicalDataTemplate and ObservableCollection containing Children

I'm trying to get this to work but unfortunately I have no idea what I'm doing wrong!我正在努力让它发挥作用,但不幸的是我不知道我做错了什么! I've looked into every uestion asked so far containing TreeView and the HierarchicalDataTemplate.到目前为止,我已经调查了包含 TreeView 和 HierarchicalDataTemplate 的所有问题。

Here's the problem: I have a TreeView and would like to show the folder structure with all SubFolders and Files in it.问题是:我有一个 TreeView 并且想显示其中包含所有子文件夹和文件的文件夹结构。 To do so I created a class with the necessary Items:为此,我创建了一个包含必要项目的类:

public class FolderItem : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public FolderItem()
    {
        Files = new ObservableCollection<FileItem>();
        SubFolders = new ObservableCollection<FolderItem>();
    }

    #region:PrivateVariables
    private DirectoryInfo _Info;
    private ObservableCollection<FileItem> _Files;
    private ObservableCollection<FolderItem> _SubFolders;
    #endregion

    public DirectoryInfo Info
    {
        get { return _Info; }
        set
        {
            _Info = value;
            OnPropertyChanged("Info");
        }
    }
    public ObservableCollection<FileItem> Files
    {
        get { return _Files; }
        set
        {
            _Files = value;
            OnPropertyChanged("Files");
        }
    }
    public ObservableCollection<FolderItem> SubFolders
    {
        get { return _SubFolders; }
        set
        {
            _SubFolders = value;
            OnPropertyChanged("SubFolders");
        }
    }
}
public class FileItem : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #region:PrivateVariables
    private FileInfo _Info;
    #endregion

    public FileInfo Info
    {
        get { return _Info; }
        set
        {
            _Info = value;
            OnPropertyChanged("Info");
        }
    }
}

In the code I now loop through all Folders and Files and the ObservableCollection folders now shows the correct data!在代码中,我现在遍历所有文件夹和文件,ObservableCollection 文件夹现在显示正确的数据! The code I use looks like this:我使用的代码如下所示:

public void StartExtraction(string sPath)
{
    if (Directory.Exists(sPath))
    {
        FolderItem newFolder = new FolderItem();
        newFolder.Info = new DirectoryInfo(sPath);

        GetFileCount(sPath, newFolder);

        Application.Current.Dispatcher.Invoke((Action)delegate ()
        {
            ViewModel_ZVLB.folders.Add(newFolder);
        });
    }
}

public void GetFileCount(string sPath, FolderItem actualFolder)
{
    if (Directory.Exists(sPath))
    {
        foreach (string fileName in Directory.GetFiles(sPath))
        {
            FileItem newFile = new FileItem();
            newFile.Info = new FileInfo(fileName);
            actualFolder.Files.Add(newFile);
        }

        foreach (string subFolder in Directory.GetDirectories(sPath))
        {
            FolderItem newSubFolder = new FolderItem();
            newSubFolder.Info = new DirectoryInfo(subFolder);
            actualFolder.SubFolders.Add(newSubFolder);

            GetFileCount(subFolder, newSubFolder);
        }
    }
}

With this OC I go to the XAML and tried a lot to show the Data:有了这个 OC,我去 XAML 并尝试了很多来显示数据:

    <TreeView ItemsSource="{Binding folders}">
    <TreeView.Resources>
        <HierarchicalDataTemplate ItemsSource="{Binding folders}" DataType="{x:Type local:FolderItem}">
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Info.Name}" />
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.Resources>

    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        </Style>
    </TreeView.ItemContainerStyle>

    <TreeView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Info.FullName}" FontSize="16" FontWeight="Bold" />
        </DataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Even with another HierarchicalDataTemplate it won't work.即使使用另一个 HierarchicalDataTemplate 它也不起作用。

Is there anything I did wrong?我做错了什么吗? Or is it just not working with ObservableCollections?或者它只是不适用于 ObservableCollections?

Intereisting is also that after the Update of Visual Studio 2017 a new Error appeared: As "folders" for Tpye "ViewModel_ZVLB" a instancemenber is expected!有趣的是,在 Visual Studio 2017 更新后,出现了一个新错误:作为 Tpye“ViewModel_ZVLB”的“文件夹”,需要一个实例! (translated from German) Has this something to do with my problem? (翻译自德语)这与我的问题有关吗?

Thanks for your help!谢谢你的帮助!

In my opinion, if you want to work with Treeviews, it is easier to use only one Observablecollection for the children.在我看来,如果你想使用 Treeviews,为孩子们只使用一个 Observablecollection 会更容易。

First I create a generic class for each element of your Tree.首先,我为 Tree 的每个元素创建一个通用类。 The Folder and File classes inherits from it. Folder 和 File 类继承自它。

public class TreeItem: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class FolderItem:TreeItem
{
    public FolderItem()
    {
        Elems = new ObservableCollection<TreeItem>();
    }

    #region:PrivateVariables
    private DirectoryInfo _Info;
    private ObservableCollection<TreeItem> _Elems;
    #endregion

    public DirectoryInfo Info
    {
        get { return _Info; }
        set
        {
            _Info = value;
            OnPropertyChanged("Info");
        }
    }

    public ObservableCollection<TreeItem> Elems
    {
        get { return _Elems; }
        set
        {
            _Elems = value;
            OnPropertyChanged("Elems");
        }
    }
}
public class FileItem : TreeItem
{

    #region:PrivateVariables
    private FileInfo _Info;
    #endregion

    public FileInfo Info
    {
        get { return _Info; }
        set
        {
            _Info = value;
            OnPropertyChanged("Info");
        }
    }
}

Here is the XAML code:这是 XAML 代码:

    <TreeView ItemsSource="{Binding folders}">
        <TreeView.Resources>
            <HierarchicalDataTemplate ItemsSource="{Binding Elems}" DataType="{x:Type local:FolderItem}">
                <TextBlock Text="{Binding Info.Name}" FontWeight="Bold"/>
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type local:FileItem}">
                <TextBlock Text="{Binding Info.Name}" />
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>

Of course you need to update your filling function:当然你需要更新你的填充函数:

    public void GetFileCount(string sPath, FolderItem actualFolder)
    {
        if (Directory.Exists(sPath))
        {
            foreach (string fileName in Directory.GetFiles(sPath))
            {
                FileItem newFile = new FileItem();
                newFile.Info = new FileInfo(fileName);
                actualFolder.Elems.Add(newFile);
            }

            foreach (string subFolder in Directory.GetDirectories(sPath))
            {
                FolderItem newSubFolder = new FolderItem();
                newSubFolder.Info = new DirectoryInfo(subFolder);
                actualFolder.Elems.Add(newSubFolder);

                GetFileCount(subFolder, newSubFolder);
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM