我正在创建一个XML查看器,它应该能够读取每个XML文件并将其放在树视图中。
我的目标是创建一个xmlviewer控件,用户应该能够在自己的实现中更改某些例程。我提供了提供基本功能的默认实现,以便XML查看器至少显示默认行为。我试着用管道和代表来做这个。
到目前为止我所拥有的:
主窗口.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>
主窗口.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);
}
}
}
}
XmlTreeView项目类
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
如你所见,我很难正确显示我的树状图。有人想办法解决这个问题吗?
最佳答案
好的,所以你要实现一个树视图,它有扩展点,
为XML节点定制颜色/标题。
为此,您为每个xmltreeviewitem添加了几个公共委托,哪个调用方
可以重写以提供自己的颜色/标题等。
当前解决方案的问题是,只有根节点获得自定义的着色委托。
在构造根xml节点时,通过构造新的xmltreeviewitem加载所有子节点,新的xmltreeviewitem具有loadcolor委托的默认实现。
您需要将委托重写复制到每个新创建的节点中,或者保留对已重写委托的根节点的引用。
另一个问题是,整个xmltreeviewitem树是在构造函数中生成的,并且委托重写只在之后提供:
newItem = new XMLTreeViewItem(node);
newItem._LoadColor = new LoadColorDelegate(newItem.LoadColorPlumbed);
newItem._LoadColor.Invoke(node);
这意味着在执行loadcolor.invoke时,整个树已经构造好并初始化了其颜色。_ loadcolor=new loadcolorDelegate将覆盖已传递给所有子级的委托,\u loadcolor.invoke将只对根节点上色。
我建议如何解决这个问题:
将loadheader/checkforchildren/loadcolor方法(希望允许重写)移动到xmltreeview类,并在其中公开为公共属性:
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不必为委托着色,但可能会使此类用户的自定义复杂化,因为他们需要覆盖每个节点中的委托。
关于c# - C#XML Treeview(管道),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14500376/