c# - 具有 HierarchicalDataTemplate 和包含子项的 ObservableCollection 的 WPF TreeView

标签 c# wpf treeview observablecollection hierarchicaldatatemplate

我正在努力让它工作,但不幸的是我不知道我做错了什么!到目前为止,我已经调查了每个包含 TreeView 和 HierarchicalDataTemplate 的问题。

问题是:我有一个 TreeView 并想显示其中包含所有子文件夹和文件的文件夹结构。为此,我创建了一个包含必要项目的类:

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");
        }
    }
}

在代码中,我现在循环遍历所有文件夹和文件,ObservableCollection 文件夹现在显示正确的数据!我使用的代码如下所示:

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);
        }
    }
}

有了这个 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>

即使使用另一个 HierarchicalDataTemplate 也无法正常工作。

我做错了什么吗?或者它只是不适用于 ObservableCollections?

有趣的是,在 Visual Studio 2017 更新后,出现了一个新错误:作为 Tpye“ViewModel_ZVLB”的“文件夹”,需要一个实例! (译自德语) 这与我的问题有关吗?

感谢您的帮助!

最佳答案

在我看来,如果你想使用 Treeviews,为 children 只使用一个 Observablecollection 会更容易。

首先,我为树的每个元素创建一个通用类。 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");
        }
    }
}

这是 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>

当然你需要更新你的填充函数:

    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);
            }
        }
    }

关于c# - 具有 HierarchicalDataTemplate 和包含子项的 ObservableCollection 的 WPF TreeView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46947894/

相关文章:

c# - 如何以编程方式添加契约(Contract)属性?

c# - wpf强制构建可视化树

java - 是否可以显示 Java 代码的树结构?

c# - 选择项目时如何避免winforms treeview图标发生变化

c# - 单击另一个按钮无法获取组合框选择的项目值

wpf - WPF 中的多列 TreeView

c# - 在 C# 中创建 COM 代理服务器 (exe)

c# - 来自 Service.OnStart 的信号初始化失败

c# - 如何使用 Wpf、MVVM 获取图像像素位置和 RGB 值?

.net - Prism 事件聚合 - 未触发订阅者