2012-03-13 5 views
0

현재 인터넷 탐색기에서 xml 파일을 열 때와 같이 쉬운 xml 파일을 쉽게 탐색 할 수있는 간단한 xml 뷰어 컨트롤을 만들고 있습니다.treeview 컨트롤에서 xml 태그 끝내기

using System.Windows.Controls; 
using System.Windows.Data; 
using System.Xml; 

namespace WpfApplication1.CustomControl 
{ 
    /// <summary> 
    /// Interaction logic for Viewer.xaml 
    /// </summary> 
    public partial class Viewer : UserControl 
    { 
     private XmlDocument _xmldocument; 

     public Viewer() 
     { 
      InitializeComponent(); 
     } 

     public XmlDocument xmlDocument 
     { 
      get { return _xmldocument; } 
      set 
      { 
       _xmldocument = value; 
       BindXMLDocument(); 
      } 
     } 

     private void BindXMLDocument() 
     { 
      if (_xmldocument == null) 
      { 
       xmlTree.ItemsSource = null; 
       return; 
      } 

      XmlDataProvider provider = new XmlDataProvider(); 
      provider.Document = _xmldocument; 
      Binding binding = new Binding(); 
      binding.Source = provider; 
      binding.XPath = "child::node()"; 
      xmlTree.SetBinding(TreeView.ItemsSourceProperty, binding); 
     } 
    } 
} 

내 문제가 지금은 자식 노드의 종료 태그를 표시 할 것입니다 : 코드 숨김

<UserControl x:Class="WpfApplication1.CustomControl.Viewer" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:xmlstack="clr-namespace:System.Xml;assembly=System.Xml"> 

    <UserControl.Resources> 
     <SolidColorBrush x:Key="xmlValueBrush" Color="Blue" /> 
     <SolidColorBrush x:Key="xmAttributeBrush" Color="Red" /> 
     <SolidColorBrush x:Key="xmlTagBrush" Color="DarkMagenta" /> 
     <SolidColorBrush x:Key="xmlMarkBrush" Color="Blue" /> 

     <DataTemplate x:Key="attributeTemplate"> 
      <StackPanel Margin="3,0,0,0" 
         HorizontalAlignment="Center" 
         Orientation="Horizontal"> 
       <TextBlock Foreground="{StaticResource xmAttributeBrush}" Text="{Binding Path=Name}" /> 
       <TextBlock Foreground="{StaticResource xmlMarkBrush}" Text="=&quot;" /> 
       <TextBlock Foreground="{StaticResource xmlValueBrush}" Text="{Binding Path=Value}" /> 
       <TextBlock Foreground="{StaticResource xmlMarkBrush}" Text="&quot;" /> 
      </StackPanel> 
     </DataTemplate> 

     <Style TargetType="{x:Type TreeViewItem}"> 
      <Setter Property="IsExpanded" Value="True" /> 
     </Style> 

     <HierarchicalDataTemplate x:Key="treeViewTemplate" ItemsSource="{Binding XPath=child::node()}"> 
      <StackPanel Margin="3,0,0,0" 
         HorizontalAlignment="Center" 
         Orientation="Horizontal"> 
       <TextBlock x:Name="startTag" 
          HorizontalAlignment="Center" 
          Foreground="{StaticResource xmlMarkBrush}" 
          Text="&lt;" /> 

       <TextBlock x:Name="xmlTag" 
          Margin="0" 
          HorizontalAlignment="Center" 
          Foreground="{StaticResource xmlTagBrush}" 
          Text="{Binding Path=Name}" /> 

       <ItemsControl HorizontalAlignment="Center" 
           ItemsSource="{Binding Path=Attributes}" 
           ItemTemplate="{StaticResource attributeTemplate}"> 
        <ItemsControl.ItemsPanel> 
         <ItemsPanelTemplate> 
          <StackPanel Orientation="Horizontal" /> 
         </ItemsPanelTemplate> 
        </ItemsControl.ItemsPanel> 
       </ItemsControl> 

       <TextBlock x:Name="endTag" 
          HorizontalAlignment="Center" 
          Foreground="{StaticResource xmlMarkBrush}" 
          Text="&gt;" /> 
      </StackPanel> 

      <HierarchicalDataTemplate.Triggers> 
       <DataTrigger Binding="{Binding NodeType}"> 
        <DataTrigger.Value> 
         <xmlstack:XmlNodeType>Text</xmlstack:XmlNodeType> 
        </DataTrigger.Value> 
        <Setter TargetName="xmlTag" Property="Text" Value="{Binding InnerText}" /> 
        <Setter TargetName="xmlTag" Property="Foreground" Value="Blue" /> 
        <Setter TargetName="startTag" Property="Visibility" Value="Collapsed" /> 
        <Setter TargetName="endTag" Property="Visibility" Value="Collapsed" /> 
       </DataTrigger> 

       <DataTrigger Binding="{Binding HasChildNodes}" Value="False"> 
        <Setter TargetName="endTag" Property="Text" Value=" /&gt;" /> 
       </DataTrigger> 
      </HierarchicalDataTemplate.Triggers> 
     </HierarchicalDataTemplate> 
    </UserControl.Resources> 

    <Grid> 
     <TreeView Name="xmlTree" 
        Grid.Row="2" 
        Grid.ColumnSpan="2" 
        ItemTemplate="{StaticResource treeViewTemplate}" /> 
    </Grid> 
</UserControl> 

이 들어

은 내가 MSDN 포럼에 좋은 컨트롤을 발견 별 표시 다음 예 :

<root> 
    <node>Test*</node>* 
*</root>* 

나는 좋은이 제안하고,이를 실현하는 방법을 모른다 이온?

미리 감사드립니다.

+0

그들이 개막 태그를 어떻게했는지 살펴보십시오 (예 : '') 그리고 거기에서부터 .. –

+0

예, 끝 노드를 만드는 방법을 알고 있지만 끝 태그가 하위 노드 뒤에 표시되도록 textblocks를 추가 할 위치를 얻지 못합니다. : | –

+0

HierDT의 마지막 TextBlock 아래에 넣으면 어떻게됩니까? –

답변

0

컨트롤 (WebBrowser)을 사용하여 해결했습니다.

나는 TreeView으로 더 좋은 해결책을 찾을 수 없습니다,하지만 전체 MVVM이기 때문에,이 코드를 완전 만족 해요 :

Public Class AttachedWebBrowserProperties 

#Region "BindableXmlDataProperty" 

    Public Shared ReadOnly BindableXmlDataProperty As DependencyProperty = _ 
      DependencyProperty.RegisterAttached("BindableXmlData", _ 
             GetType(String), _ 
             GetType(AttachedWebBrowserProperties), _ 
             New UIPropertyMetadata(Nothing, AddressOf BindableXmlDataPropertyChanged)) 

    Public Shared Function GetBindableXmlData(ByVal obj As DependencyObject) As ICommand 
     Return CType(obj.GetValue(BindableXmlDataProperty), ICommand) 
    End Function 

    Public Shared Sub SetBindableXmlData(ByVal obj As DependencyObject, ByVal value As String) 
     obj.SetValue(BindableXmlDataProperty, value) 
    End Sub 

    Public Shared Sub BindableXmlDataPropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs) 
     Dim browser As WebBrowser = TryCast(d, WebBrowser) 

     If browser IsNot Nothing Then 
      Dim xmldata As String = TryCast(e.NewValue, String) 

      If xmldata IsNot Nothing Then 
       browser.NavigateToString(xmldata) 
      End If 
     End If 
    End Sub 

#End Region 

End Class 

하는 것은 다음 추가 :

BindableXmlData라는 웹 브라우저 컨트롤에 대한 종속성 속성 만들기 다음 내용이 포함 된 리소스로 XmlToHtmlStylesheet.xslt이라는 새로운 파일을 솔루션에 추가하십시오.

<!-- 
| 
| XSLT REC Compliant Version of IE5 Default Stylesheet 
| 
| Original version by Jonathan Marsh ([email protected]) 
| http://msdn.microsoft.com/xml/samples/defaultss/defaultss.xsl 
| 
| Conversion to XSLT 1.0 REC Syntax by Steve Muench ([email protected]) 
| 
+--> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="no" method="html"/> 
    <xsl:template match="/"> 
    <HTML> 
     <HEAD> 
     <SCRIPT> 
      <xsl:comment> 
      <![CDATA[ 
        function f(e){ 
        if (e.className=="ci") { 
         if (e.children(0).innerText.indexOf("\n")>0) fix(e,"cb"); 
        } 
        if (e.className=="di") { 
         if (e.children(0).innerText.indexOf("\n")>0) fix(e,"db"); 
        } e.id=""; 
        } 
        function fix(e,cl){ 
        e.className=cl; 
        e.style.display="block"; 
        j=e.parentElement.children(0); 
        j.className="c"; 
        k=j.children(0); 
        k.style.visibility="visible"; 
        k.href="#"; 
        } 
        function ch(e) { 
        mark=e.children(0).children(0); 
        if (mark.innerText=="+") { 
         mark.innerText="-"; 
         for (var i=1;i<e.children.length;i++) { 
         e.children(i).style.display="block"; 
         } 
        } 
        else if (mark.innerText=="-") { 
         mark.innerText="+"; 
         for (var i=1;i<e.children.length;i++) { 
         e.children(i).style.display="none"; 
         } 
        } 
        } 
        function ch2(e) { 
        mark=e.children(0).children(0); 
        contents=e.children(1); 
        if (mark.innerText=="+") { 
         mark.innerText="-"; 
         if (contents.className=="db"||contents.className=="cb") { 
         contents.style.display="block"; 
         } 
         else { 
         contents.style.display="inline"; 
         } 
        } 
        else if (mark.innerText=="-") { 
         mark.innerText="+"; 
         contents.style.display="none"; 
        } 
        } 
        function cl() { 
        e=window.event.srcElement; 
        if (e.className!="c") { 
         e=e.parentElement; 
         if (e.className!="c") { 
         return; 
         } 
        } 
        e=e.parentElement; 
        if (e.className=="e") { 
         ch(e); 
        } 
        if (e.className=="k") { 
         ch2(e); 
        } 
        } 
        function ex(){} 
        function h(){window.status=" ";} 
        document.onclick=cl; 
       ]]> 
      </xsl:comment> 
     </SCRIPT> 
     <STYLE> 
      BODY {font:x-small 'Verdana'; margin-right:1.5em} 
      .c {cursor:hand} 
      .b {color:red; font-family:'Courier New'; font-weight:bold; 
      text-decoration:none} 
      .e {margin-left:1em; text-indent:-1em; margin-right:1em} 
      .k {margin-left:1em; text-indent:-1em; margin-right:1em} 
      .t {color:#990000} 
      .xt {color:#990099} 
      .ns {color:red} 
      .dt {color:green} 
      .m {color:blue} 
      .tx {font-weight:bold} 
      .db {text-indent:0px; margin-left:1em; margin-top:0px; 
      margin-bottom:0px;padding-left:.3em; 
      border-left:1px solid #CCCCCC; font:small Courier} 
      .di {font:small Courier} 
      .d {color:blue} 
      .pi {color:blue} 
      .cb {text-indent:0px; margin-left:1em; margin-top:0px; 
      margin-bottom:0px;padding-left:.3em; font:small Courier; 
      color:#888888} 
      .ci {font:small Courier; color:#888888} 
      PRE {margin:0px; display:inline} 
     </STYLE> 
     </HEAD> 
     <BODY class="st"> 
     <xsl:apply-templates/> 
     </BODY> 
    </HTML> 
    </xsl:template> 
    <xsl:template match="processing-instruction()"> 
    <DIV class="e"> 
     <SPAN class="b"> 
     <xsl:call-template name="entity-ref"> 
      <xsl:with-param name="name">nbsp</xsl:with-param> 
     </xsl:call-template> 
     </SPAN> 
     <SPAN class="m"> 
     <xsl:text>&lt;?</xsl:text> 
     </SPAN> 
     <SPAN class="pi"> 
     <xsl:value-of select="name(.)"/> 
     <xsl:value-of select="."/> 
     </SPAN> 
     <SPAN class="m"> 
     <xsl:text>?></xsl:text> 
     </SPAN> 
    </DIV> 
    </xsl:template> 
    <xsl:template match="processing-instruction('xml')"> 
    <DIV class="e"> 
     <SPAN class="b"> 
     <xsl:call-template name="entity-ref"> 
      <xsl:with-param name="name">nbsp</xsl:with-param> 
     </xsl:call-template> 
     </SPAN> 
     <SPAN class="m"> 
     <xsl:text>&lt;?</xsl:text> 
     </SPAN> 
     <SPAN class="pi"> 
     <xsl:text>xml </xsl:text> 
     <xsl:for-each select="@*"> 
      <xsl:value-of select="name(.)"/> 
      <xsl:text>="</xsl:text> 
      <xsl:value-of select="."/> 
      <xsl:text>" </xsl:text> 
     </xsl:for-each> 
     </SPAN> 
     <SPAN class="m"> 
     <xsl:text>?></xsl:text> 
     </SPAN> 
    </DIV> 
    </xsl:template> 
    <xsl:template match="@*"> 
    <SPAN> 
     <xsl:attribute name="class"> 
     <xsl:if test="xsl:*/@*"> 
      <xsl:text>x</xsl:text> 
     </xsl:if> 
     <xsl:text>t</xsl:text> 
     </xsl:attribute> 
     <xsl:value-of select="name(.)"/> 
    </SPAN> 
    <SPAN class="m">="</SPAN> 
    <B> 
     <xsl:value-of select="."/> 
    </B> 
    <SPAN class="m">"</SPAN> 
    </xsl:template> 
    <xsl:template match="text()"> 
    <DIV class="e"> 
     <SPAN class="b"> </SPAN> 
     <SPAN class="tx"> 
     <xsl:value-of select="."/> 
     </SPAN> 
    </DIV> 
    </xsl:template> 
    <xsl:template match="comment()"> 
    <DIV class="k"> 
     <SPAN> 
     <A STYLE="visibility:hidden" class="b" onclick="return false" onfocus="h()">-</A> 
     <SPAN class="m"> 
      <xsl:text>&lt;!--</xsl:text> 
     </SPAN> 
     </SPAN> 
     <SPAN class="ci" id="clean"> 
     <PRE> 
      <xsl:value-of select="."/> 
     </PRE> 
     </SPAN> 
     <SPAN class="b"> 
     <xsl:call-template name="entity-ref"> 
      <xsl:with-param name="name">nbsp</xsl:with-param> 
     </xsl:call-template> 
     </SPAN> 
     <SPAN class="m"> 
     <xsl:text>--></xsl:text> 
     </SPAN> 
     <SCRIPT>f(clean);</SCRIPT> 
    </DIV> 
    </xsl:template> 
    <xsl:template match="*"> 
    <DIV class="e"> 
     <DIV STYLE="margin-left:1em;text-indent:-2em"> 
     <SPAN class="b"> 
      <xsl:call-template name="entity-ref"> 
      <xsl:with-param name="name">nbsp</xsl:with-param> 
      </xsl:call-template> 
     </SPAN> 
     <SPAN class="m">&lt;</SPAN> 
     <SPAN> 
      <xsl:attribute name="class"> 
      <xsl:if test="xsl:*"> 
       <xsl:text>x</xsl:text> 
      </xsl:if> 
      <xsl:text>t</xsl:text> 
      </xsl:attribute> 
      <xsl:value-of select="name(.)"/> 
      <xsl:if test="@*"> 
      <xsl:text> </xsl:text> 
      </xsl:if> 
     </SPAN> 
     <xsl:apply-templates select="@*"/> 
     <SPAN class="m"> 
      <xsl:text>/></xsl:text> 
     </SPAN> 
     </DIV> 
    </DIV> 
    </xsl:template> 
    <xsl:template match="*[node()]"> 
    <DIV class="e"> 
     <DIV class="c"> 
     <A class="b" href="#" onclick="return false" onfocus="h()">-</A> 
     <SPAN class="m">&lt;</SPAN> 
     <SPAN> 
      <xsl:attribute name="class"> 
      <xsl:if test="xsl:*"> 
       <xsl:text>x</xsl:text> 
      </xsl:if> 
      <xsl:text>t</xsl:text> 
      </xsl:attribute> 
      <xsl:value-of select="name(.)"/> 
      <xsl:if test="@*"> 
      <xsl:text> </xsl:text> 
      </xsl:if> 
     </SPAN> 
     <xsl:apply-templates select="@*"/> 
     <SPAN class="m"> 
      <xsl:text>></xsl:text> 
     </SPAN> 
     </DIV> 
     <DIV> 
     <xsl:apply-templates/> 
     <DIV> 
      <SPAN class="b"> 
      <xsl:call-template name="entity-ref"> 
       <xsl:with-param name="name">nbsp</xsl:with-param> 
      </xsl:call-template> 
      </SPAN> 
      <SPAN class="m"> 
      <xsl:text>&lt;/</xsl:text> 
      </SPAN> 
      <SPAN> 
      <xsl:attribute name="class"> 
       <xsl:if test="xsl:*"> 
       <xsl:text>x</xsl:text> 
       </xsl:if> 
       <xsl:text>t</xsl:text> 
      </xsl:attribute> 
      <xsl:value-of select="name(.)"/> 
      </SPAN> 
      <SPAN class="m"> 
      <xsl:text>></xsl:text> 
      </SPAN> 
     </DIV> 
     </DIV> 
    </DIV> 
    </xsl:template> 
    <xsl:template match="*[text() and not (comment() or processing-instruction())]"> 
    <DIV class="e"> 
     <DIV STYLE="margin-left:1em;text-indent:-2em"> 
     <SPAN class="b"> 
      <xsl:call-template name="entity-ref"> 
      <xsl:with-param name="name">nbsp</xsl:with-param> 
      </xsl:call-template> 
     </SPAN> 
     <SPAN class="m"> 
      <xsl:text>&lt;</xsl:text> 
     </SPAN> 
     <SPAN> 
      <xsl:attribute name="class"> 
      <xsl:if test="xsl:*"> 
       <xsl:text>x</xsl:text> 
      </xsl:if> 
      <xsl:text>t</xsl:text> 
      </xsl:attribute> 
      <xsl:value-of select="name(.)"/> 
      <xsl:if test="@*"> 
      <xsl:text> </xsl:text> 
      </xsl:if> 
     </SPAN> 
     <xsl:apply-templates select="@*"/> 
     <SPAN class="m"> 
      <xsl:text>></xsl:text> 
     </SPAN> 
     <SPAN class="tx"> 
      <xsl:value-of select="."/> 
     </SPAN> 
     <SPAN class="m">&lt;/</SPAN> 
     <SPAN> 
      <xsl:attribute name="class"> 
      <xsl:if test="xsl:*"> 
       <xsl:text>x</xsl:text> 
      </xsl:if> 
      <xsl:text>t</xsl:text> 
      </xsl:attribute> 
      <xsl:value-of select="name(.)"/> 
     </SPAN> 
     <SPAN class="m"> 
      <xsl:text>></xsl:text> 
     </SPAN> 
     </DIV> 
    </DIV> 
    </xsl:template> 
    <xsl:template match="*[*]" priority="20"> 
    <DIV class="e"> 
     <DIV STYLE="margin-left:1em;text-indent:-2em" class="c"> 
     <A class="b" href="#" onclick="return false" onfocus="h()">-</A> 
     <SPAN class="m">&lt;</SPAN> 
     <SPAN> 
      <xsl:attribute name="class"> 
      <xsl:if test="xsl:*"> 
       <xsl:text>x</xsl:text> 
      </xsl:if> 
      <xsl:text>t</xsl:text> 
      </xsl:attribute> 
      <xsl:value-of select="name(.)"/> 
      <xsl:if test="@*"> 
      <xsl:text> </xsl:text> 
      </xsl:if> 
     </SPAN> 
     <xsl:apply-templates select="@*"/> 
     <SPAN class="m"> 
      <xsl:text>></xsl:text> 
     </SPAN> 
     </DIV> 
     <DIV> 
     <xsl:apply-templates/> 
     <DIV> 
      <SPAN class="b"> 
      <xsl:call-template name="entity-ref"> 
       <xsl:with-param name="name">nbsp</xsl:with-param> 
      </xsl:call-template> 
      </SPAN> 
      <SPAN class="m"> 
      <xsl:text>&lt;/</xsl:text> 
      </SPAN> 
      <SPAN> 
      <xsl:attribute name="class"> 
       <xsl:if test="xsl:*"> 
       <xsl:text>x</xsl:text> 
       </xsl:if> 
       <xsl:text>t</xsl:text> 
      </xsl:attribute> 
      <xsl:value-of select="name(.)"/> 
      </SPAN> 
      <SPAN class="m"> 
      <xsl:text>></xsl:text> 
      </SPAN> 
     </DIV> 
     </DIV> 
    </DIV> 
    </xsl:template> 
    <xsl:template name="entity-ref"> 
    <xsl:param name="name"/> 
    <xsl:text disable-output-escaping="yes">&amp;</xsl:text> 
    <xsl:value-of select="$name"/> 
    <xsl:text>;</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 
가 새 창을 생성 (또는 내 경우, UserControl을에) :

<UserControl x:Class="AdditionalXmlView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:ui="clr-namespace:MyApplication.Framework"> 
    <WebBrowser ui:AttachedWebBrowserProperties.BindableXmlData="{Binding XmlData}" /> 
</UserControl> 

이 같은 뷰 모델을 만들기 :

Imports System.Xml 
Imports System.Xml.Xsl 
Imports System.Text 
Imports System.IO 
Imports System.ComponentModel 

Public Class AdditionalXmlViewModel 
    Implements INotifyPropertyChanged 

    Private _XmlData As String 
    Public Property XmlData() As String 
     Get 
      Return _XmlData 
     End Get 
     Set(ByVal value As String) 
      _XmlData = value 
      OnPropertyChanged("XmlData") 
     End Set 
    End Property 

    Public Sub LoadXmlData(ByVal xmlDocument As XmlDocument) 
     Dim sb As New StringBuilder(2500) 
     Dim xslt As New XslCompiledTransform() 
     Dim stylesheetStream As Stream = GetType(AdditionalXmlView).Assembly.GetManifestResourceStream("MyApplication.Framework.XmlToHtmlStylesheet.xslt") 

     If stylesheetStream IsNot Nothing Then 
      Dim xmlReader As XmlReader = xmlReader.Create(stylesheetStream) 

      xslt.Load(xmlReader) 
      Dim settings As New XmlWriterSettings() 
      Dim dest As XmlWriter = XmlWriter.Create(sb, settings) 
      xslt.Transform(xmlDocument, dest) 
     End If 

     XmlData = sb.ToString() 
    End Sub 


    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged 
    Public Sub OnPropertyChanged(ByVal propertyName As String) 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) 
    End Sub 
End Class 

XMLDATA 뷰와 뷰 모델을 생성하고 설정합니다

Public Class XYZ 
    Private additionalView As AdditionalXmlView 
    Private additionalViewModel As AdditionalXmlViewModel 

    Private Sub CreateInstances() 
     additionalViewModel = New AdditionalXmlViewModel() 
     additionalView = New AdditionalXmlView() 
     additionalView.DataContext = additionalViewModel 
    End Sub 

    Private Sub SetXmlDataOfAdditionalView() 
     Dim xmlDocument As New XmlDocument() 
     xmlDocument.Load("myXmlFile.xml") 

     additionalViewModel.LoadXmlData(xmlDocument) 
    End Sub 
End Class