WPF - Как отобразить TreeView со смесью самоссылающихся и внешних сущностей - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь визуализировать TreeView со смесью самоссылающихся и внешних сущностей, но не могу найти какое-либо решение, которое работает ..

У меня есть следующие модели:

# Folder
-> string Name
-> Folder ParentFolder
-> Collection<Folder> Children
-> Collection<Document> Documents

# Document
-> string Name
-> Folder Folder

Я пытаюсь отобразить его в виде иерархии файловой системы следующим образом:

+ Folder 1
  + Folder 1.1
    - Doc 1
    - Doc 2
+ Folder 2
  + Folder 2.1
  + Folder 2.2
    - Doc 3
  - Doc 4

ViewModel, привязанный к представлению, содержит Collection<Folder> Folders.

Я пробовал много разных комбинация в XAML с простым связыванием и MultiBinding, но безуспешно. Вот мой текущий XAML (который не работает, потому что не отображает иерархию):

<TreeView ItemsSource="{Binding Folders}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type model:Folder}">
            <HierarchicalDataTemplate.ItemsSource>
                <MultiBinding>
                    <Binding Path="Children" />
                    <Binding Path="Documents" />
                </MultiBinding>
            </HierarchicalDataTemplate.ItemsSource>

            <TextBlock Text="{Binding Name}" Background="Blue"/>
        </HierarchicalDataTemplate>

        <DataTemplate DataType="{x:Type model:Document}">
            <TextBlock Text="{Binding Name}" Background="Red"/>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

Я также попробовал следующее, которое отображает иерархию папок, но не документы ( я думаю, из-за того, что нигде в XAML не указано свойство Documents, но не знаю, как ..):

<TreeView ItemsSource="{Binding Folders}">
    <TreeView.Resources>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}" DataType="{x:Type model:Folder}">
            <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>

        <DataTemplate DataType="{x:Type model:Document}">
            <TextBlock Text="{Binding Name}" Background="Red"/>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

Спасибо за вашу помощь!

1 Ответ

1 голос
/ 22 апреля 2020

Ваш текущий XAML должен работать, если вы просто определяете и используете конвертер, который создает составную коллекцию папок и документов:

public class Converter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        IEnumerable<object> folders = values[0] as IEnumerable<object>;
        IEnumerable<object> docs = values[1] as IEnumerable<object>;

        if (folders != null && docs != null)
            return Enumerable.Concat(folders, docs);
        else if (folders != null)
            return folders;
        else if (docs != null)
            return docs;

        return null;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
        throw new NotSupportedException();
}

XAML:

<TreeView ItemsSource="{Binding Folders}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type model:Folder}">
            <HierarchicalDataTemplate.ItemsSource>
                <MultiBinding>
                    <MultiBinding.Converter>
                        <model:Converter />
                    </MultiBinding.Converter>
                    <Binding Path="Children" />
                    <Binding Path="Documents" />
                </MultiBinding>
            </HierarchicalDataTemplate.ItemsSource>
            <TextBlock Text="{Binding Name}" Background="Blue"/>
        </HierarchicalDataTemplate>

        <DataTemplate DataType="{x:Type model:Document}">
            <TextBlock Text="{Binding Name}" Background="Red"/>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>
...