загрузка структуры дерева TreeView из XML

307
27 апреля 2017, 12:44

Я пытаюсь отобразить элементы из XML в TreeView используя wpf MVVM

это мой XML:

<Root>
    <Group GroupType = "Group1">
        <Table>
            <Name>TableName1.1</Name>       
            <Tag>TableTag1.1</Tag>
        </Table>
        <Table>
            <Name>TableName1.2</Name>       
            <Tag>TableTag1.2</Tag>
        </Table>
        <Group GroupType = "Group1.1">
            <Table>
                <Name>TableName1.1.1</Name>     
                <Tag>TableTag1.1.1</Tag>
            </Table>        
        </Group>
    </Group>
    <Group GroupType = "Group2">
        <Table>
            <Name>TableName2.1</Name>       
            <Tag>TableTag2.1</Tag>
        </Table>        
    </Group>
</Root>

это моя ViewModel

public class NavigationViewModel:ViewModelBase
    {
        private NavigationGroup _group;
        public NavigationViewModel()
        {
            _group = new NavigationGroup();
        }
        [XmlElement("Name", typeof(string))]
        public string Name
        {
            get
            {
                return _group.Name;
            }
            set
            {
                _group.Name = value;
                this.OnPropertyChanged("Name");
            }
        }
        [XmlArray("Group")]
        [XmlArrayItem("Table")]
        public ObservableCollection<NavigationViewModel> Children { get; set; }
    }

это моя model

public class NavigationGroup
    {
        public string Name;
        public ObservableCollection<NavigationTable> Tables;
        public NavigationGroup()
        {
            Tables = new ObservableCollection<NavigationTable>();
        }
    }

и конечно же XAML

        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding  NavigVM.Children}"  >
                <TextBlock Text="{Binding Name}"/>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>

проблема заключается в том что отображаются только TableName. А как сделать так чтобы отображались еще GroupType

Group1
    tableName1.1
    tableName1.2
    Group1.1
        TableName1.1.1
Group2
    TableName2.1

небольшие изменения, спасибо VladD

public class NavigationViewModel:ViewModelBase
    {

        public NavigationViewModel()
        {
        }


        private bool _isSelected;
        public bool isSelected
        {
            get
            {
                return _isSelected;
            }
            set
            {
                _isSelected = value;
            }
        }

        [XmlElement("Table")]
        public ObservableCollection<NavigationTable> Tables { get; set; }

        private ObservableCollection<NavigationGroup> _groups;
        [XmlElement("Group")]
        public ObservableCollection<NavigationGroup> Groups
        {
            get
            {
                return _groups;
            }
            set
            {
                _groups = value;
                this.OnPropertyChanged("Groups");
            }
        }

        **public List<object> Items**
        {
            get
            {
                List<object> childNodes = new List<object>();
                foreach (var group in this.Groups)
                    childNodes.Add(group);
                foreach (var entry in this.Tables)
                    childNodes.Add(entry);
                return childNodes;
            }
        }
    }

XAML

TreeView DataContext="{Binding NavigVM}" ItemsSource="{Binding}"  >
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type local:NavigationGroup}" ItemsSource="{Binding items}">
                    <TextBlock Text="{Binding GroupType}" />
                </HierarchicalDataTemplate>
                <DataTemplate DataType="{x:Type local:NavigationTable}" >
                    <TextBlock Text="{Binding Name}" />
                </DataTemplate>
            </TreeView.Resources>

        </TreeView>

но Treeview ничего не показывает

Answer 1

У меня десериализация работает вот так:

[XmlType]
public class Group
{
    [XmlElement("Table")]
    public List<Table> Tables { get; set; }
    [XmlElement("Group")]
    public List<Group> Groups { get; set; }
    [XmlAttribute]
    public string GroupType { get; set; }
}
[XmlType]
public class Table
{
    public string Name { get; set; }
    public string Tag { get; set; }
}
using (var file = File.OpenRead(path))
{
    var serializer = new XmlSerializer(typeof(Group),
                                       new XmlRootAttribute { ElementName = "Root" });
    var result = (Group)serializer.Deserialize(file);
}

(Вам, понятно, нужно будет добавить ViewModelBase и реализацию INotifyPropertyChanged.)

Обновление:

С вот такими модификациями:

[XmlType]
public class NavigationGroup
{
    [XmlElement("Table")]
    public List<NavigationTable> Tables { get; set; }
    [XmlElement("Group")]
    public List<NavigationGroup> Groups { get; set; }
    [XmlIgnore]
    public IEnumerable<object> Items => Tables.Cast<object>().Concat(Groups);
    [XmlAttribute]
    public string GroupType { get; set; }
}
[XmlType]
public class NavigationTable
{
    public string Name { get; set; }
    public string Tag { get; set; }
}

и десериализацией

using (var file = File.OpenRead(path))
{
    var serializer = new XmlSerializer(typeof(NavigationGroup),
                           new XmlRootAttribute { ElementName = "Root" });
    var result = (NavigationGroup)serializer.Deserialize(file);
}

и вот таким XAML'ом:

<TreeView ItemsSource="{Binding Groups}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:NavigationGroup}"
                                  ItemsSource="{Binding Items}">
            <TextBlock Text="{Binding GroupType}" Background="Green"/>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type local:NavigationTable}">
            <TextBlock Background="Yellow">
                <Run Text="{Binding Name}"/><Run Text="/"/><Run Text="{Binding Tag}"/>
            </TextBlock>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

получается следующая картинка:

READ ALSO
генератор строк [требует правки]

генератор строк [требует правки]

Возможно туповатый вопрос но все таки его задам: как можно с генерировать строку чтобы она совпала с той, которую я ввел через ConsoleReadLine(); ? Или...

193