2016-08-25 28 views
0

XMLファイルをツリービューコントロールに追加するXMLファイルエディタを構築しようとしています。ノードと属性に基づいて、編集可能なテキストボックスやその他のコントロールを表示する必要があります。私はこのXMLデータをシリアル化してデシリアライズして、別のモジュールで処理します。XMLファイルをWPFにバインドするTreeview

私はこれに従うことを試みていますStackoverflow questionしかし、私はそれを動作させることはできません、何もコントロールにバインドします。私はXAMLとMVVMについてかなり新しいです。ので、任意のヘルプは、提案は本当に感謝されます。

All I am getting is this

PS:[兼ね備え]入力は、XMLファイルですので、あなたの提案に基づいて、私はMVVMを通じ​​てクラスをツリ​​ービューまたはserialzedするXMLを直接結合するために開いています。

XMLファイル構造:

<?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> 

コード

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#コード

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

*********** UPDATE信号を取り込むことができるが、私は第2の子供をどのように配置するのか分からない。ルート今すぐ

************アップデート**************

@ JHによると、CompositeCollectionを使用すると、問題が解決しました。 Save XMLコマンドは例外をスローしているようですが、XMLは現在Treeviewに取り込まれています。

public Signals Signals { get; set; } 

をしかし、それは次のようになります:クラス連動して

+0

お困りですか?何がうまくいかないの? –

+0

@EdPlunkett更新された質問を親切に読んでください。 XMLデータがツリービューコントロールにバインドされていません。私はツリービューでこの1つの静的な項目を取得しています – Shahzad

答えて

1

、あなたが持っているあなたの編集に

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

回答:

は1つのだけのアイテムのソースを持つことができますので、私シグナルとルートを1つのコレクションにまとめることをお勧めします。インターロッククラスを次のように変更してください:

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

これは、シグナルとルートの両方を1つのコレクションにまとめます。ルート・タイプにHierarchicalDataTemplateを追加し、もちろん、

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

をそして:あなたはそれがItemSourceだために子供を使用するようにXAMLを変更する必要がありますFYI

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

を - このソリューションは、から来た:

WPF Treeview Databinding Hierarchal Data with mixed types

+0

ありがとう、私はTreeviewでルートを取得することができましたが、 "ルート"はまだ失われています。私は別のHierarchicalDataTemplateを作成しようとしましたが、何も返されません。 別のツリービューを作成する必要がありますか、または単一のTreeviewで "Route"と "Signal"をバインドできますか? PS:xamlと画像で質問を更新しました。 – Shahzad

+1

@Shahzad - 編集 –

+0

を参照してください。私はファイルを保存するときにこれらのクラスがどのようにxmIに変わるか分かりませんが、これらの行で何か考えました。私は今、ルートとして子供たちになっています。私は今これにしたがってRouteの子を縛りつけようとします。何かが南になると更新する。あなたは深刻な頭痛から私を助けました:) – Shahzad

関連する問題