Завершение тега xml в древовидной структуре - PullRequest
0 голосов
/ 13 марта 2012

В настоящее время я работаю над простым элементом управления средством просмотра XML, чтобы отображать некоторые файлы XML с простыми возможностями навигации, например при открытии файла XML в обозревателе Интернета.

Для этого я нашел хороший элемент управления на форумах msdn:

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

Code-Behind:

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

Моя проблема сейчас заключается в том, что я хочу отобразить конечный тег дочерних узлов в следующем примере, отмеченном звездочками:

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

Я не знаю, как это реализовать, есть ли хорошие предложения?

Заранее спасибо.

1 Ответ

0 голосов
/ 14 марта 2012

Я решил это с помощью элемента управления WebBrowser.

Я не нашел хорошего решения с TreeView, но я полностью удовлетворен этим кодом, потому что он полный MVVM:

Создайте свойство зависимостей для элементов управления WebBrowser с именем BindableXmlData:

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

Затем добавьте новый файл к вашему решению с именем XmlToHtmlStylesheet.xslt в качестве встроенного ресурса со следующим содержимым:

<!--
 |
 | XSLT REC Compliant Version of IE5 Default Stylesheet
 |
 | Original version by Jonathan Marsh (jmarsh@xxxxxxxxxxxxx)
 | http://msdn.microsoft.com/xml/samples/defaultss/defaultss.xsl
 |
 | Conversion to XSLT 1.0 REC Syntax by Steve Muench (smuench@xxxxxxxxxx)
 |
 +-->

  
  
    
      
        
          
            <![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
          
        
        
          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}
        
      
      
        
      
    
  
  
    
      
        
          nbsp
        
      
      
        <?
      
      
        
        
      
      
        ?>
      
    
  
  
    
      
        
          nbsp
        
      
      
        <?
      
      
        xml 
        
          
          ="
          
          " 
        
      
      
        ?>
      
    
  
  
    
      
        
          x
        
        t
      
      
    
    ="
    
      
    
    "
  
  
    
       
      
        
      
    
  
  
    
      
        
        
          <!--
        
      
      
        
          
        
NBSP-> f (чистый); NBSP <</SPAN> ИксT/> - <</SPAN> ИксT>
NBSP</</SPAN> ИксT>
NBSP<</SPAN> ИксT> </ </SPAN> ИксT> - <</SPAN> ИксT>
NBSP</</SPAN> ИксT>
&;

Создайте новое окно (или в моем случае пользовательский контроль):

<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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...