将 XML 文件绑定到 WPF Treeview [英] Binding XML file to WPF Treeview

查看:60
本文介绍了将 XML 文件绑定到 WPF Treeview的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个 XML 文件编辑器,我想在其中将 XML 文件添加到树视图控件,并且基于它的节点和属性,我必须显示可编辑的文本框或其他控件.我序列化和反序列化此 xml 数据以在其他模块中处理.

我正在尝试关注这个

PS:输入是一个 xml 文件,因此根据您的建议,我愿意通过 MVVM [首选] 将 xml 直接绑定到树视图或序列化类.

XML 文件结构:

 <?xml version="1.0" encoding="utf-8"?><互锁 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><信号><信号参考="SignalRef_1"><aspectSpeedDependencies><aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas"><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/></aspectSpeedDependency><aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas"><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/></aspectSpeedDependency><aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas"><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/></aspectSpeedDependency></aspectSpeedDependencies></信号><信号参考="SignalRef_1"><aspectSpeedDependencies><aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas"><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/></aspectSpeedDependency><aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas"><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/></aspectSpeedDependency><aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas"><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/><targetRef ref="TargetRef"/></aspectSpeedDependency></aspectSpeedDependencies></信号></信号><路线><路由id="1"><开始><signalRef ref="pro.Routes.Route.Start.SignalRef.Ref"/></开始><目标><signalRef ref="Target.SingalRef"/></目标><元素><switchRef><switch ref="Ref" course="Left"/></switchRef><levelcrossingRef><levelcrossing ref="Ref" beam="Beam"/><levelcrossing ref="Ref" beam="Beam"/><levelcrossing ref="Ref" beam="Beam"/></levelcrossingRef><trackCircuitBorder ref="Ref"/><trackCircuitBorder ref="Ref"/><trackCircuitBorder ref="Ref"/></trainDetectorRef></元素><flankElements>Flank</flankElements><routePriority rank="1"/></路线></路线></互锁>

背后的代码

使用系统;使用 System.Collections.Generic;使用 System.Diagnostics;使用 System.IO;使用 System.Linq;使用 System.Text;使用 System.Threading.Tasks;使用 System.Windows;使用 System.Windows.Controls;使用 System.Windows.Data;使用 System.Windows.Documents;使用 System.Windows.Input;使用 System.Windows.Media;使用 System.Windows.Media.Imaging;使用 System.Windows.Shapes;使用 System.Xml;使用 System.Xml.Serialization;//使用CoreElements.Core.Interlocking;使用 System.Xml.Linq;使用 System.Reflection;命名空间 TreeviewTest.Stck{///<总结>///Window1.xaml 的交互逻辑///</总结>公共部分类 Window1 : 窗口{公共窗口 1(){初始化组件();}私有无效 ExecutedLoadXML(对象发送者,ExecutedRoutedEventArgs e){string executableLocation = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);string xslLocation = System.IO.Path.Combine(executableLocation, "Interlocking.xml");XDocument xmlData = XDocument.Load(xslLocation, LoadOptions.None);var Interlocking = XmlSerializationHelper.LoadFromXML(xmlData.ToString());var children = new List();children.Add(互锁);treeView1.ItemsSource = null;treeView1.Items.Clear();treeView1.ItemsSource = 儿童;}私有无效 ExecutedSaveXML(对象发送者,ExecutedRoutedEventArgs e){var planList = treeView1.ItemsSource as IList;if (planList != null && planList.Count > 0){//Kludge 强制挂起的编辑更新treeView1.Focus();//替换为实际的保存代码!Debug.WriteLine(planList[0].GetXml());}}}公共静态类 CustomCommands{public static readonly RoutedUICommand LoadXMLCommand = new RoutedUICommand("Load XML", "LoadXML", typeof(Window1));public static readonly RoutedUICommand SaveXMLCommand = new RoutedUICommand("Save XML", "SaveXML", typeof(Window1));}公共静态类 XmlSerializationHelper{公共静态字符串 GetXml(T obj,XmlSerializer 序列化程序,bool omitStandardNamespaces){使用 (var textWriter = new StringWriter()){XmlWriterSettings settings = new XmlWriterSettings();settings.Indent = true;//用于装饰目的.settings.IndentChars = " ";//用于装饰目的.使用 (var xmlWriter = XmlWriter.Create(textWriter, settings)){如果(省略标准命名空间){XmlSerializerNamespaces ns = new XmlSerializerNamespaces();ns.Add("", "");//禁用 xmlns:xsi 和 xmlns:xsd 行.serializer.Serialize(xmlWriter, obj, ns);}别的{serializer.Serialize(xmlWriter, obj);}}返回 textWriter.ToString();}}public static string GetXml(this T obj, bool omitNamespace){XmlSerializer 序列化器 = new XmlSerializer(obj.GetType());返回 GetXml(obj, serializer, omitNamespace);}public static string GetXml(this T obj){返回 GetXml(obj, false);}public static T LoadFromXML(这个字符串xmlString){返回 xmlString.LoadFromXML(new XmlSerializer(typeof(T)));}public static T LoadFromXML(这个字符串 xmlString,XmlSerializer 序列号){T returnValue = default(T);使用 (StringReader reader = new StringReader(xmlString)){对象结果 = serial.Deserialize(reader);如果(结果是 T){returnValue = (T)result;}}返回返回值;}public static T LoadFromFile(字符串文件名){XmlSerializer serial = new XmlSerializer(typeof(T));尝试{使用 (var fs = new FileStream(filename, FileMode.Open)){对象结果 = serial.Deserialize(fs);如果(结果是 T){返回 (T) 结果;}}}捕获(异常前){Debug.WriteLine(ex.ToString());扔;}返回默认值(T);}}}

XAML:

 <Window.CommandBindings><CommandBinding Command="o:CustomCommands.LoadXMLCommand" Executed="ExecutedLoadXML"/><CommandBinding Command="o:CustomCommands.SaveXMLCommand" Executed="ExecutedSaveXML"/></Window.CommandBindings><窗口.资源><HierarchicalDataTemplate DataType="{x:Type o:Interlocking}" ItemsSource="{Binding Path=Signals}"><TextBlock Text="互锁"></TextBlock></HierarchicalDataTemplate ><HierarchicalDataTemplate DataType="{x:Type o:Signals}" ItemsSource="{Binding Path=Signal}"><TextBlock Text="信号"></TextBlock></HierarchicalDataTemplate ><!--<HierarchicalDataTemplate DataType="{x:Type o:Signal}" ItemsSource="{Binding Path=AspectSpeedDependencies}"><TextBlock Text="信号"></TextBlock></HierarchicalDataTemplate ><HierarchicalDataTemplate DataType="{x:Type o:AspectSpeedDependencies}" ItemsSource="{Binding Path=AspectSpeedDependency}"><TextBlock Text="AspectSpeedDependencies"></TextBlock></HierarchicalDataTemplate >--><HierarchicalDataTemplate DataType="{x:Type o:Signal}" ItemsSource="{Binding Path=AspectSpeedDependencies}"><Grid Margin="3" MinWidth="300"><Grid.RowDefinitions><行定义/></Grid.RowDefinitions><Grid.ColumnDefinitions><列定义/><列定义/></Grid.ColumnDefinitions><TextBlock Text="Ref" Grid.Column="0" Grid.Row="0"/><TextBox Text="{Binding Path=Ref, Mode=TwoWay}" Grid.Column="1" Grid.Row="0"/></网格></HierarchicalDataTemplate ><HierarchicalDataTemplate DataType="{x:Type o:AspectSpeedDependencies}" ItemsSource="{Binding Path=AspectSpeedDependency}"><TextBlock Text="AspectSpeedDependencies"></TextBlock></HierarchicalDataTemplate ><HierarchicalDataTemplate DataType="{x:Type o:AspectSpeedDependency}" ItemsSource="{Binding Path=TargetRef}"><Border BorderBrush="Gray" BorderThickness="1" MinWidth="300"><StackPanel Height="auto" Width="auto"><TextBlock Text="AspectSpeedDependency:"/><StackPanel Orientation="水平"><TextBlock Text="Aspect:" Margin="1"/><TextBox Text="{Binding Path=Aspect, Mode=TwoWay}" Margin="1"/><TextBlock Text="VApproach:" Margin="1"/><TextBox Text="{Binding Path=VApproach, Mode=TwoWay}" Margin="1"/><TextBlock Text="VPass:" Margin="1"/><TextBox Text="{Binding Path=VPass, Mode=TwoWay}" Margin="1"/></StackPanel><!--<TextBlock Text="Aspect:" Grid.Column="0" Grid.Row="2"/><TextBox Text="{Binding Path=Aspect, Mode=TwoWay}" Grid.Column="1" Grid.Row="2"/><TextBlock Text="VApproach:" Grid.Column="0" Grid.Row="3"/><TextBox Text="{Binding Path=VApproach, Mode=TwoWay}" Grid.Column="1" Grid.Row="3"/><TextBlock Text="VPass:" Grid.Column="0" Grid.Row="4"/><TextBox Text="{Binding Path=VPass, Mode=TwoWay}" Grid.Column="1" Grid.Row="4"/>--></StackPanel></边框></HierarchicalDataTemplate ><DataTemplate DataType="{x:Type o:TargetRef}"><Border BorderBrush="Brown" BorderThickness="1" MinWidth="300"><Grid Margin="3" ><Grid.RowDefinitions><行定义/><行定义/><行定义/><行定义/></Grid.RowDefinitions><Grid.ColumnDefinitions><列定义/><列定义/></Grid.ColumnDefinitions><TextBlock Text="Ref:" Grid.Column="0" Grid.Row="0"/><TextBox Text="{Binding Path=Ref, Mode=TwoWay}" Grid.Column="1" Grid.Row="0"/></网格></边框></数据模板 >

 <DockPanel><ToolBarTray DockPanel.Dock="Top"><工具栏><Button Command="o:CustomCommands.LoadXMLCommand" Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"/><Button Command="o:CustomCommands.SaveXMLCommand" Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"/></工具栏></ToolBarTray><Grid DockPanel.Dock="底部"><TreeView Margin="3" Name="treeView1"><TreeView.ItemContainerStyle><Style TargetType="{x:Type TreeViewItem}"><Setter Property="IsExpanded" Value="True"/></风格></TreeView.ItemContainerStyle></树视图></网格></DockPanel></窗口>

XML C# 代码

 使用系统;使用 System.Collections.Generic;使用 System.Linq;使用 System.Text;使用 System.Threading.Tasks;使用 System.Xml.Serialization;命名空间 TreeviewTest.Stck{[XmlRoot(ElementName = "targetRef")]公共类 TargetRef{[XmlAttribute(AttributeName = "ref")]公共字符串 Ref { 获取;放;}}[XmlRoot(ElementName = "aspectSpeedDependency")]公共类 AspectSpeedDependency{[XmlElement(ElementName = "targetRef")]公共列表目标引用 { 获取;放;}[XmlAttribute(AttributeName = "aspect")]公共字符串方面{获取;放;}[XmlAttribute(AttributeName = "vApproach")]公共字符串 VApproach { 获取;放;}[XmlAttribute(AttributeName = "vPass")]公共字符串 VPass { 获取;放;}}[XmlRoot(ElementName = "aspectSpeedDependencies")]公共类 AspectSpeedDependencies{[XmlElement(ElementName = "aspectSpeedDependency")]公共列表AspectSpeedDependency { 获取;放;}}[XmlRoot(ElementName = "信号")]公共课信号{[XmlElement(ElementName = "aspectSpeedDependencies")]公共列表<AspectSpeedDependencies>AspectSpeedDependencies { 获取;放;}[XmlAttribute(AttributeName = "ref")]公共字符串 Ref { 获取;放;}}[XmlRoot(ElementName = "signals")]公共类信号{[XmlElement(ElementName = "signal")]公共列表<信号>信号{得到;放;}}[XmlRoot(ElementName = "signalRef")]公共类 SignalRef{[XmlAttribute(AttributeName = "ref")]公共字符串 Ref { 获取;放;}}[XmlRoot(ElementName = "start")]公开课开始{[XmlElement(ElementName = "signalRef")]公共 SignalRef SignalRef { 获取;放;}}[XmlRoot(ElementName = "target")]公开课目标{[XmlElement(ElementName = "signalRef")]公共 SignalRef SignalRef { 获取;放;}}[XmlRoot(ElementName = "switch")]公共类开关{[XmlAttribute(AttributeName = "ref")]公共字符串 Ref { 获取;放;}[XmlAttribute(AttributeName = "课程")]公共字符串课程{获取;放;}}[XmlRoot(ElementName = "switchRef")]公共类 SwitchRef{[XmlElement(ElementName = "switch")]公共开关开关{获取;放;}}[XmlRoot(ElementName = "levelcrossing")]公共课Levelcrossing{[XmlAttribute(AttributeName = "ref")]公共字符串 Ref { 获取;放;}[XmlAttribute(AttributeName = "beam")]公共字符串梁{获取;放;}}[XmlRoot(ElementName = "levelcrossingRef")]公共类 LevelcrossingRef{[XmlElement(ElementName = "levelcrossing")]公共列表平交{得到;放;}}[XmlRoot(ElementName = "trackCircuitBorder")]公共类 TrackCircuitBorder{[XmlAttribute(AttributeName = "ref")]公共字符串 Ref { 获取;放;}}[XmlRoot(ElementName = "trainDetectorRef")]公共类 TrainDetectorRef{[XmlElement(ElementName = "trackCircuitBorder")]公共列表TrackCircuitBorder { 获取;放;}}[XmlRoot(ElementName = "元素")]公共类元素{[XmlElement(ElementName = "switchRef")]公共 SwitchRef SwitchRef { 获取;放;}[XmlElement(ElementName = "levelcrossingRef")]公共 LevelcrossingRef LevelcrossingRef { get;放;}[XmlElement(ElementName = "trainDetectorRef")]公共 TrainDetectorRef TrainDetectorRef { get;放;}}[XmlRoot(ElementName = "routePriority")]公共类 RoutePriority{[XmlAttribute(AttributeName = "rank")]公共字符串排名{获取;放;}}[XmlRoot(ElementName = "route")]公开课路线{[XmlElement(ElementName = "start")]公共开始开始{得到;放;}[XmlElement(ElementName = "target")]公共目标目标{得到;放;}[XmlElement(ElementName = "元素")]公共元素元素{获取;放;}[XmlElement(ElementName = "flankElements")]公共字符串 FlankElements { 获取;放;}[XmlElement(ElementName = "routePriority")]公共 RoutePriority RoutePriority { 获取;放;}[XmlAttribute(AttributeName = "id")]公共字符串 ID { 获取;放;}}[XmlRoot(ElementName = "routes")]公开课路线{[XmlElement(ElementName = "route")]公共路线路线{得到;放;}}[XmlRoot(ElementName = "interlocking")]公开课互锁{[XmlElement(ElementName = "信号")]公共列表<信号>信号 { 得到;放;}[XmlElement(ElementName = "routes")]公共列表<路线>路线{得到;放;}[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]公共字符串 Xsi { 获取;放;}[XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]公共字符串 Xsd { 获取;放;}}}

************更新***********

我能够填充信号,但我不知道我将如何填充第二个孩子,现在路由

****************更新****************

根据@J.H 的回答,使用 CompositeCollection 解决了这个问题.保存 XML 命令似乎抛出异常,但 XML 现在已填充到 Treeview 中.

解决方案

在 Interlocking 课程中,您有:

public Signals Signals { get;放;}

但应该是:

公共列表<信号>信号 { 得到;放;}

回答您的

您只能拥有一个物品来源,因此我建议您将信号和路线合并为一个集合.将您的互锁类更改为:

[XmlRoot(ElementName = "interlocking")]公开课互锁{[XmlElement(ElementName = "信号")]公共列表<信号>信号 { 得到;放;}[XmlElement(ElementName = "routes")]公共列表<路线>路线{得到;放;}[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]公共字符串 Xsi { 获取;放;}[XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]公共字符串 Xsd { 获取;放;}公共 IList 儿童{得到{返回新的复合集合(){new CollectionContainer() { Collection = Signals },new CollectionContainer() { Collection = Routes }};}}}

注意到新的属性 Children?它将 Signals 和 Routes 组合成一个集合.然后,您需要修改 XAML 以使用 Children 作为它的 ItemSource:

<TextBlock Text="互锁"></TextBlock></HierarchicalDataTemplate >

当然,还要为 Routes 类型添加 HierarchicalDataTemplate:

<TextBlock Text="路由"></TextBlock></HierarchicalDataTemplate >

仅供参考 - 此解决方案来自:

混合类型的 WPF Treeview 数据绑定分层数据

I am trying to build a XML file editor, where I want to add XML file to treeview control, and based on it's nodes and attributes, i have to show editable textboxes or other controls. I serializing and deserializing this xml data to process in someother module.

I am trying to follow this Stackoverflow question but I cannot get it working, nothing binds with the control. I am fairly new to XAML and MVVM. so any help , suggestion will be really appreciated.

PS: Input is a xml file, so based on your suggestions i am open to bind xml directly to treeview or serialzed classes through MVVM[preffered].

XML File Structure:

    <?xml version="1.0" encoding="utf-8"?>
<interlocking xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <signals>
    <signal ref="SignalRef_1">
      <aspectSpeedDependencies>
        <aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas">
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
        </aspectSpeedDependency>
        <aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas">
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
        </aspectSpeedDependency>
        <aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas">
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
        </aspectSpeedDependency>
      </aspectSpeedDependencies>
    </signal>
    <signal ref="SignalRef_1">
      <aspectSpeedDependencies>
        <aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas">
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
        </aspectSpeedDependency>
        <aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas">
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
        </aspectSpeedDependency>
        <aspectSpeedDependency aspect="REF" vApproach="VApproach" vPass="Vpas">
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
          <targetRef ref="TargetRef" />
        </aspectSpeedDependency>
      </aspectSpeedDependencies>
    </signal>
  </signals>
  <routes>
    <route id="1">
      <start>
        <signalRef ref="pro.Routes.Route.Start.SignalRef.Ref" />
      </start>
      <target>
        <signalRef ref="Target.SingalRef" />
      </target>
      <elements>
        <switchRef>
          <switch ref="Ref" course="Left" />
        </switchRef>
        <levelcrossingRef>
          <levelcrossing ref="Ref" beam="Beam" />
          <levelcrossing ref="Ref" beam="Beam" />
          <levelcrossing ref="Ref" beam="Beam" />
        </levelcrossingRef>
        <trainDetectorRef>
          <trackCircuitBorder ref="Ref" />
          <trackCircuitBorder ref="Ref" />
          <trackCircuitBorder ref="Ref" />
        </trainDetectorRef>
      </elements>
      <flankElements>Flank</flankElements>
      <routePriority rank="1" />
    </route>
  </routes>
</interlocking>

Code Behind

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Xml;
using System.Xml.Serialization;
//using CoreElements.Core.Interlocking;
using System.Xml.Linq;
using System.Reflection;

namespace TreeviewTest.Stck
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }


        private void ExecutedLoadXML(object sender, ExecutedRoutedEventArgs e)
        {

            string executableLocation = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string xslLocation = System.IO.Path.Combine(executableLocation, "Interlocking.xml");

            XDocument xmlData = XDocument.Load(xslLocation, LoadOptions.None);
            var Interlocking = XmlSerializationHelper.LoadFromXML<Interlocking>(xmlData.ToString());

            var children = new List<Interlocking>();
            children.Add(Interlocking);

            treeView1.ItemsSource = null;
            treeView1.Items.Clear();
            treeView1.ItemsSource = children;
        }

        private void ExecutedSaveXML(object sender, ExecutedRoutedEventArgs e)
        {
            var planList = treeView1.ItemsSource as IList<Interlocking>;
            if (planList != null && planList.Count > 0)
            {
                // Kludge to force pending edits to update
                treeView1.Focus();
                // Replace with actual save code!
                Debug.WriteLine(planList[0].GetXml());
            }
        }
    }

    public static class CustomCommands
    {
        public static readonly RoutedUICommand LoadXMLCommand = new RoutedUICommand("Load XML", "LoadXML", typeof(Window1));

        public static readonly RoutedUICommand SaveXMLCommand = new RoutedUICommand("Save XML", "SaveXML", typeof(Window1));
    }

    public static class XmlSerializationHelper
    {
        public static string GetXml<T>(T obj, XmlSerializer serializer, bool omitStandardNamespaces)
        {
            using (var textWriter = new StringWriter())
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;        // For cosmetic purposes.
                settings.IndentChars = "    "; // For cosmetic purposes.
                using (var xmlWriter = XmlWriter.Create(textWriter, settings))
                {
                    if (omitStandardNamespaces)
                    {
                        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                        ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
                        serializer.Serialize(xmlWriter, obj, ns);
                    }
                    else
                    {
                        serializer.Serialize(xmlWriter, obj);
                    }
                }
                return textWriter.ToString();
            }
        }

        public static string GetXml<T>(this T obj, bool omitNamespace)
        {
            XmlSerializer serializer = new XmlSerializer(obj.GetType());
            return GetXml(obj, serializer, omitNamespace);
        }

        public static string GetXml<T>(this T obj)
        {
            return GetXml(obj, false);
        }

        public static T LoadFromXML<T>(this string xmlString)
        {
            return xmlString.LoadFromXML<T>(new XmlSerializer(typeof(T)));
        }

        public static T LoadFromXML<T>(this string xmlString, XmlSerializer serial)
        {
            T returnValue = default(T);

            using (StringReader reader = new StringReader(xmlString))
            {
                object result = serial.Deserialize(reader);
                if (result is T)
                {
                    returnValue = (T)result;
                }
            }
            return returnValue;
        }

        public static T LoadFromFile<T>(string filename)
        {
            XmlSerializer serial = new XmlSerializer(typeof(T));
            try
            {
                using (var fs = new FileStream(filename, FileMode.Open))
                {
                    object result = serial.Deserialize(fs);
                    if (result is T)
                    {
                        return (T)result;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                throw;
            }
            return default(T);
        }
    }
}

XAML:

 <Window x:Class="Test_Thesis.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:o="clr-namespace:Test_Thesis"
        mc:Ignorable="d"
      Title="Window1" Height="300" Width="600">
    <Window.CommandBindings>
        <CommandBinding Command="o:CustomCommands.LoadXMLCommand"  Executed="ExecutedLoadXML"/>
        <CommandBinding Command="o:CustomCommands.SaveXMLCommand" Executed="ExecutedSaveXML"/>
    </Window.CommandBindings>
    <Window.Resources>
        <HierarchicalDataTemplate  DataType="{x:Type o:Interlocking}" ItemsSource="{Binding Path=Signals}">
            <TextBlock Text="Interlocking">
            </TextBlock>
        </HierarchicalDataTemplate >
        <HierarchicalDataTemplate  DataType="{x:Type o:Signals}" ItemsSource="{Binding Path=Signal}">
            <TextBlock Text="Signal">
            </TextBlock>
        </HierarchicalDataTemplate >

        <!--<HierarchicalDataTemplate  DataType="{x:Type o:Signal}" ItemsSource="{Binding Path=AspectSpeedDependencies}">
            <TextBlock Text="Signals">
            </TextBlock>
        </HierarchicalDataTemplate >
        <HierarchicalDataTemplate  DataType="{x:Type o:AspectSpeedDependencies}" ItemsSource="{Binding Path=AspectSpeedDependency}">
            <TextBlock Text="AspectSpeedDependencies">
            </TextBlock>
        </HierarchicalDataTemplate >-->

        <HierarchicalDataTemplate  DataType="{x:Type o:Signal}" ItemsSource="{Binding Path=AspectSpeedDependencies}">
            <Grid Margin="3" MinWidth="300">
                <Grid.RowDefinitions>
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <TextBlock Text="Ref" Grid.Column="0" Grid.Row="0"/>
                <TextBox Text="{Binding Path=Ref, Mode=TwoWay}" Grid.Column="1" Grid.Row="0"/>
            </Grid>
        </HierarchicalDataTemplate >
        <HierarchicalDataTemplate  DataType="{x:Type o:AspectSpeedDependencies}" ItemsSource="{Binding Path=AspectSpeedDependency}">
            <TextBlock Text="AspectSpeedDependencies">
            </TextBlock>
        </HierarchicalDataTemplate >

        <HierarchicalDataTemplate  DataType="{x:Type o:AspectSpeedDependency}" ItemsSource="{Binding Path=TargetRef}">

            <Border BorderBrush="Gray" BorderThickness="1" MinWidth="300">
                <StackPanel Height="auto" Width="auto">
                    <TextBlock Text="AspectSpeedDependency:" />

                        <StackPanel Orientation="Horizontal">

                            <TextBlock Text="Aspect:" Margin="1"/>
                        <TextBox Text="{Binding Path=Aspect, Mode=TwoWay}" Margin="1"/>
                        <TextBlock Text="VApproach:" Margin="1"/>
                        <TextBox Text="{Binding Path=VApproach, Mode=TwoWay}" Margin="1"/>
                        <TextBlock Text="VPass:" Margin="1"/>
                        <TextBox Text="{Binding Path=VPass, Mode=TwoWay}" Margin="1"/>
                    </StackPanel>



                        <!--<TextBlock Text="Aspect:" Grid.Column="0" Grid.Row="2"/>
                        <TextBox Text="{Binding Path=Aspect, Mode=TwoWay}" Grid.Column="1" Grid.Row="2"/>
                        <TextBlock Text="VApproach:" Grid.Column="0" Grid.Row="3"/>
                        <TextBox Text="{Binding Path=VApproach, Mode=TwoWay}" Grid.Column="1" Grid.Row="3"/>
                        <TextBlock Text="VPass:" Grid.Column="0" Grid.Row="4"/>
                        <TextBox Text="{Binding Path=VPass, Mode=TwoWay}" Grid.Column="1" Grid.Row="4"/>-->



                </StackPanel>

            </Border>
        </HierarchicalDataTemplate >

        <DataTemplate  DataType="{x:Type o:TargetRef}">
            <Border BorderBrush="Brown" BorderThickness="1" MinWidth="300">
                <Grid Margin="3" >
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="Ref:" Grid.Column="0" Grid.Row="0"/>
                    <TextBox Text="{Binding Path=Ref, Mode=TwoWay}" Grid.Column="1" Grid.Row="0"/>



                </Grid>
            </Border>
        </DataTemplate >

    </Window.Resources>
    <DockPanel>
        <ToolBarTray DockPanel.Dock="Top">
            <ToolBar>
                <Button Command="o:CustomCommands.LoadXMLCommand" Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"/>
                <Button Command="o:CustomCommands.SaveXMLCommand" Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"/>
            </ToolBar>
        </ToolBarTray>
        <Grid DockPanel.Dock="Bottom">
            <TreeView Margin="3" Name="treeView1">
                <TreeView.ItemContainerStyle>
                    <Style TargetType="{x:Type TreeViewItem}">
                        <Setter Property="IsExpanded" Value="True" />
                    </Style>
                </TreeView.ItemContainerStyle>
            </TreeView>
        </Grid>
    </DockPanel>
</Window>

XML C# code

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;


namespace TreeviewTest.Stck
{


    [XmlRoot(ElementName = "targetRef")]
    public class TargetRef
    {
        [XmlAttribute(AttributeName = "ref")]
        public string Ref { get; set; }
    }

    [XmlRoot(ElementName = "aspectSpeedDependency")]
    public class AspectSpeedDependency
    {
        [XmlElement(ElementName = "targetRef")]
        public List<TargetRef> TargetRef { get; set; }
        [XmlAttribute(AttributeName = "aspect")]
        public string Aspect { get; set; }
        [XmlAttribute(AttributeName = "vApproach")]
        public string VApproach { get; set; }
        [XmlAttribute(AttributeName = "vPass")]
        public string VPass { get; set; }
    }

    [XmlRoot(ElementName = "aspectSpeedDependencies")]
    public class AspectSpeedDependencies
    {
        [XmlElement(ElementName = "aspectSpeedDependency")]
        public List<AspectSpeedDependency> AspectSpeedDependency { get; set; }
    }

    [XmlRoot(ElementName = "signal")]
    public class Signal
    {
        [XmlElement(ElementName = "aspectSpeedDependencies")]
        public List<AspectSpeedDependencies> AspectSpeedDependencies { get; set; }
        [XmlAttribute(AttributeName = "ref")]
        public string Ref { get; set; }
    }

    [XmlRoot(ElementName = "signals")]
    public class Signals
    {
        [XmlElement(ElementName = "signal")]
        public List<Signal> Signal { get; set; }
    }

    [XmlRoot(ElementName = "signalRef")]
    public class SignalRef
    {
        [XmlAttribute(AttributeName = "ref")]
        public string Ref { get; set; }
    }

    [XmlRoot(ElementName = "start")]
    public class Start
    {
        [XmlElement(ElementName = "signalRef")]
        public SignalRef SignalRef { get; set; }
    }

    [XmlRoot(ElementName = "target")]
    public class Target
    {
        [XmlElement(ElementName = "signalRef")]
        public SignalRef SignalRef { get; set; }
    }

    [XmlRoot(ElementName = "switch")]
    public class Switch
    {
        [XmlAttribute(AttributeName = "ref")]
        public string Ref { get; set; }
        [XmlAttribute(AttributeName = "course")]
        public string Course { get; set; }
    }

    [XmlRoot(ElementName = "switchRef")]
    public class SwitchRef
    {
        [XmlElement(ElementName = "switch")]
        public Switch Switch { get; set; }
    }

    [XmlRoot(ElementName = "levelcrossing")]
    public class Levelcrossing
    {
        [XmlAttribute(AttributeName = "ref")]
        public string Ref { get; set; }
        [XmlAttribute(AttributeName = "beam")]
        public string Beam { get; set; }
    }

    [XmlRoot(ElementName = "levelcrossingRef")]
    public class LevelcrossingRef
    {
        [XmlElement(ElementName = "levelcrossing")]
        public List<Levelcrossing> Levelcrossing { get; set; }
    }

    [XmlRoot(ElementName = "trackCircuitBorder")]
    public class TrackCircuitBorder
    {
        [XmlAttribute(AttributeName = "ref")]
        public string Ref { get; set; }
    }

    [XmlRoot(ElementName = "trainDetectorRef")]
    public class TrainDetectorRef
    {
        [XmlElement(ElementName = "trackCircuitBorder")]
        public List<TrackCircuitBorder> TrackCircuitBorder { get; set; }
    }

    [XmlRoot(ElementName = "elements")]
    public class Elements
    {
        [XmlElement(ElementName = "switchRef")]
        public SwitchRef SwitchRef { get; set; }
        [XmlElement(ElementName = "levelcrossingRef")]
        public LevelcrossingRef LevelcrossingRef { get; set; }
        [XmlElement(ElementName = "trainDetectorRef")]
        public TrainDetectorRef TrainDetectorRef { get; set; }
    }

    [XmlRoot(ElementName = "routePriority")]
    public class RoutePriority
    {
        [XmlAttribute(AttributeName = "rank")]
        public string Rank { get; set; }
    }

    [XmlRoot(ElementName = "route")]
    public class Route
    {
        [XmlElement(ElementName = "start")]
        public Start Start { get; set; }
        [XmlElement(ElementName = "target")]
        public Target Target { get; set; }
        [XmlElement(ElementName = "elements")]
        public Elements Elements { get; set; }
        [XmlElement(ElementName = "flankElements")]
        public string FlankElements { get; set; }
        [XmlElement(ElementName = "routePriority")]
        public RoutePriority RoutePriority { get; set; }
        [XmlAttribute(AttributeName = "id")]
        public string Id { get; set; }
    }

    [XmlRoot(ElementName = "routes")]
    public class Routes
    {
        [XmlElement(ElementName = "route")]
        public Route Route { get; set; }
    }

    [XmlRoot(ElementName = "interlocking")]
    public class Interlocking
    {
        [XmlElement(ElementName = "signals")]
        public List<Signals> Signals { get; set; }
        [XmlElement(ElementName = "routes")]
        public List<Routes> Routes { get; set; }
        [XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
        public string Xsi { get; set; }
        [XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
        public string Xsd { get; set; }
    }
 }

*********UPDATE***********

I am able to populate Signals, but I am not getting how would I will populate the second child , Routes now

*************Update***************

As per @J.H answer using CompositeCollection solved the issue. Save XML Command seems to be throwing exception but, XML is populated in Treeview now.

解决方案

In class Interlocking, you have:

public Signals Signals { get; set; }

But it should be:

public List<Signals> Signals { get; set; }

Answer to your edit:

You can only have one item source so I suggest you combine the Signals and Routes into one collection. Change your Interlocking class to this:

[XmlRoot(ElementName = "interlocking")]
public class Interlocking
{
    [XmlElement(ElementName = "signals")]
    public List<Signals> Signals { get; set; }
    [XmlElement(ElementName = "routes")]
    public List<Routes> Routes { get; set; }
    [XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string Xsi { get; set; }
    [XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string Xsd { get; set; }

    public IList Children
    {
        get
        {
            return new CompositeCollection()
            {
                new CollectionContainer() { Collection = Signals },
                new CollectionContainer() { Collection = Routes }
            };
        }
    }
}

Notice the new property Children? It combines both Signals and Routes into one collection. You will then need to modify the XAML to use Children for it's ItemSource:

<HierarchicalDataTemplate DataType="{x:Type o:Interlocking}" ItemsSource="{Binding Path=Children}">
    <TextBlock Text="Interlocking">
    </TextBlock>
</HierarchicalDataTemplate >

And, of course, add the HierarchicalDataTemplate for the Routes type:

<HierarchicalDataTemplate  DataType="{x:Type o:Routes}" ItemsSource="{Binding Path=Route}">
    <TextBlock Text="Route">
    </TextBlock>
</HierarchicalDataTemplate >

FYI - this solution came from:

WPF Treeview Databinding Hierarchal Data with mixed types

这篇关于将 XML 文件绑定到 WPF Treeview的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆