2013-01-24 6 views
3

모든 XML 파일을 읽고 트리 뷰에 넣을 수 있어야하는 XML 뷰어를 만듭니다. 목표는 XMLViewer 컨트롤을 만드는 것입니다. 사용자는 자신의 구현에서 특정 루틴을 변경할 수 있어야합니다. XML 뷰어가 적어도 기본 동작을 보여 주도록 기본 기능을 제공하는 기본 구현을 제공합니다. 나는 배관 공사 및 대의원들과 함께 이것을하려고 노력하고 있습니다.# XML Treeview (배관)

내가 지금까지 가지고 :

MainWindow.xaml

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="30*" /> 
     <RowDefinition Height="25*" /> 
     <RowDefinition Height="175*" /> 
    </Grid.RowDefinitions> 
    <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,5,0,5"> 
     <TextBlock Text="XML File" VerticalAlignment="Center" /> 
     <TextBox Name="txtPath" Width="400" IsReadOnly="True" Margin="5,0,5,0"/> 
     <Button Content="Open" Name="btnOpen" /> 
    </StackPanel> 

    <Button Name="btnPlumb" Content="Plumb the code!" Grid.Row="1"/> 
    <uc:XMLTreeView x:Name="XMLOutput" Grid.Row="2" /> 
</Grid> 

MainWindow.xaml.cs를

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     //Events 
     btnOpen.Click += new RoutedEventHandler(ClickedOnOpen); 
     btnPlumb.Click += new RoutedEventHandler(ClickedOnPlumb); 
    } 

    private void ClickedOnPlumb(object sender, RoutedEventArgs e) 
    { 
     plumbCode(); 
    } 

    private void ClickedOnOpen(object sender, RoutedEventArgs e) 
    { 
     selectXMLFile(); 
    } 

    private void selectXMLFile() 
    { 
     OpenFileDialog ofd = new OpenFileDialog(); 
     ofd.Filter = "XML-Files |*.xml"; 
     ofd.InitialDirectory = "C:\\"; 

     if (ofd.ShowDialog() == true) 
     { 
      string path = ofd.FileName; 
      txtPath.Text = path; 
      XMLOutput.processXML(path); 
     } 
    } 

    private void plumbCode() 
    { 
     XMLOutput.PlumbTheCode(); 
    } 
} 

클래스 XMLTreeView

namespace XMLViewer 
{ 
class XMLTreeView : TreeView 
{ 
    public XmlDocument doc; 

    public void processXML(string path) 
    { 
     XmlDocument document = new XmlDocument(); 
     this.doc = document; 
     doc.Load(path); 

     foreach (XmlNode node in doc.ChildNodes) 
     { 
      XMLTreeViewItem newItem = new XMLTreeViewItem(node); 
      this.AddChild(newItem); 
     } 
    } 

    public void PlumbTheCode() 
    { 
     this.Items.Clear(); 

     foreach (XmlNode node in doc.ChildNodes) 
     { 
      XMLTreeViewItem newItem; 
      newItem = new XMLTreeViewItem(node); 

      newItem._LoadColor = new LoadColorDelegate(newItem.LoadColorPlumbed); 
      newItem._LoadColor.Invoke(node); 


      this.AddChild(newItem); 
     } 



    } 
} 
} 

클래스 XMLTreeViewItem

namespace XMLViewer 
{ 

public delegate void LoadHeaderDelegate(XmlNode node); 
public delegate void LoadColorDelegate(XmlNode node); 
public delegate void CheckForChildrenDelegate(XmlNode node); 

public class XMLTreeViewItem:TreeViewItem 
{ 

    public LoadHeaderDelegate _LoadHeader { get; set; } 
    public LoadColorDelegate _LoadColor { get; set; } 
    public CheckForChildrenDelegate _CheckForChildren { get; set; } 

    public XMLTreeViewItem(XmlNode node) 
    { 
     _LoadHeader = new LoadHeaderDelegate(LoadHeader); 
     _LoadColor = new LoadColorDelegate(LoadColor); 
     _CheckForChildren = new CheckForChildrenDelegate(CheckForChildren); 

     _LoadHeader.Invoke(node); 
     _LoadColor.Invoke(node); 
     _CheckForChildren.Invoke(node); 
    } 

    #region HEADER 
    private void LoadHeader(XmlNode RootNode) 
    { 
     if (RootNode.HasChildNodes == false) 
     { 
      this.Header = RootNode.InnerText.ToUpper(); 
     } 
     else 
     { 
      this.Header = RootNode.Name.ToUpper(); 
     } 

     if (RootNode.Attributes != null) 
     { 
      foreach (XmlAttribute attr in RootNode.Attributes) 
      { 
       this.Header += " " + attr.Name + " = " + attr.InnerText; 
      } 
     } 
    } 
    #endregion 

    #region COLOR 
    private void LoadColor(XmlNode node) 
    { 
     this.Foreground = Brushes.Black; 
    } 
    public void LoadColorPlumbed(XmlNode node) 
    { 
     this.Foreground = Brushes.Green; 
    } 
    #endregion 

    #region CHILDREN 
    private void CheckForChildren(XmlNode node) 
    { 
     if (node.HasChildNodes) 
     { 
      LoadChildren(node); 
     } 
    } 

    private void LoadChildren(XmlNode RootNode) 
    { 
     foreach (XmlNode node in RootNode.ChildNodes) 
     { 
      XMLTreeViewItem newItem = new XMLTreeViewItem(node); 
      this.AddChild(newItem); 
     } 
    } 
    #endregion 
} 
} 

http://oi47.tinypic.com/34o94cw.jpg

내 목표는 :

http://i46.tinypic.com/29uua83.png

당신은 내가 올바른 내의 TreeNode를 표시하는 문제가 볼 수 있듯이. 누구든지이 문제를 해결할 생각이 있습니까?

+0

당신이 맞다고 생각하면 데이터의 MasterDetails보기가 필요합니다 (즉, 각 항목에 줄이 필요함). 나는 현재 비슷한 것을 개발하고 있지만, 선택된 항목에 대한 어린이 표현을 고수하고있다. 아마도 내 질문은 도움이됩니다. http://stackoverflow.com/questions/15447819/treeview-with-masterdetails-and-togglebutton –

답변

0

좋아요, xbox 노드에 대한 사용자 지정 색상/헤더가있는 확장 점이있는 트리보기를 구현하려고합니다. .

이렇게하려면 각 XMLTreeViewItem에 대해 여러 개의 공용 대리인을 추가해야합니다. 호출자 은 자신의 색/머리글/등을 제공하기 위해 재정의 할 수 있습니다.

현재 해결책의 문제점은 루트 노드 만 색칠을위한 사용자 지정 대리자를 가져 오는 것입니다. 루트 xml 노드가 구성 될 때 LoadColor 대리자의 기본 구현을 갖는 새 XMLTreeViewItem을 생성하여 모든 자식을로드합니다.

새로 만든 각 노드에 대리자 재정의를 복사하거나 재정의 된 대리인이있는 루트 노드에 대한 참조를 유지해야합니다.

또 다른 문제는 전체 XMLTreeViewItem 트리 생성자에서 생성되는 것입니다, 위임 우선은 이후에 제공됩니다 :

newItem = new XMLTreeViewItem(node); 

newItem._LoadColor = new LoadColorDelegate(newItem.LoadColorPlumbed); 
newItem._LoadColor.Invoke(node); 

그것은 시간에 당신이 _LoadColor.Invoke을하고 있다는 의미는, 전체 트리가 이미 구성되어 색상이 초기화되었습니다. _LoadColor = new LoadColorDelegate는 모든 자식에게 전달한 대리자를 덮어 쓰며, _LoadColor.Invoke는 루트 노드에만 색상을 지정합니다.

나는이 문제를 해결하는 것이 좋습니다 방법 :

XMLTreeView 클래스에, 거기 공용 속성으로 노출 (당신이 무시할 수있게하려면) 이동 LoadHeader/CheckForChildren/LoadColor 방법 :

private void LoadColor(XMLTreeViewItem item, XmlNode node) 
{ 
    item.Foreground = Brushes.Black; 
} 

수정 XMLTreeViewItem의 생성자는 각 노드에 XMLTreeView의 인스턴스 및 저장 부모 기준을 적용합니다 :

public XMLTreeViewItem(XmlNode node, XMLTreeView parentTreeView) 
{...} 

을 지금, 이 같은 트리를 구성 :

public void PlumbTheCode() 
{ 
    this.Items.Clear(); 

    this._LoadColor = new LoadColorDelegate(newItem.LoadColorPlumbed); 
    foreach (XmlNode node in doc.ChildNodes) 
    { 
     this.AddChild(new XMLTreeViewItem(node, this)); 
    } 
} 

대체 솔루션을 직접 XMLTreeViewItem 생성자에 새로운 색상/헤더 대의원을 통과 및 그 이하의 모든 노드에 재귀 적으로 통과하는 것입니다. 이렇게하면 XMLTreeView는 대리자 색상 표시를 지우지 만 각 노드에서 대리자를 덮어 써야하므로이 클래스의 사용자에 대한 사용자 정의가 복잡해질 수 있습니다.