gpt4 book ai didi

c# XML Treeview (Plumbing) 收藏

转载 作者:数据小太阳 更新时间:2023-10-29 02:45:46 24 4
gpt4 key购买 nike

我正在创建一个 XML 查看器,它应该能够读取每个 XML 文件并将其放入 TreeView 中。我的目标是创建一个 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);
}



}
}
}

类 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

如您所见,我无法正确显示我的树节点。有没有人有解决这个问题的想法?

最佳答案

好的,所以你正在尝试实现一个 TreeView ,它有扩展点,为 xml 节点设置自定义颜色/ header 。

为此,您为每个 XMLTreeViewItem 添加了几个公共(public)委托(delegate),调用者可以覆盖以提供自己的颜色/标题/等。

当前解决方案的问题是只有根节点获得用于着色的自定义委托(delegate)。构造根 xml 节点时,通过构造新的 XMLTreeViewItem 加载所有子节点,这些节点具有 LoadColor 委托(delegate)的默认实现。

您需要将委托(delegate)覆盖复制到每个新创建的节点中,或者保留对已覆盖委托(delegate)的根节点的引用。

另一个问题是整个 XMLTreeViewItem 树是在构造函数中生成的,并且仅在之后提供委托(delegate)覆盖:

newItem = new XMLTreeViewItem(node);

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

这意味着在您执行 _LoadColor.Invoke 时,整个树已经构建并且其颜色已初始化。 _LoadColor = new LoadColorDelegate 会覆盖您传递给所有子节点的委托(delegate),而 _LoadColor.Invoke 只会为根节点着色。

我建议如何解决这个问题:

将 LoadHeader/CheckForChildren/LoadColor 方法(您希望允许覆盖的方法)移动到 XMLTreeView 类,并在那里公开为公共(public)属性:

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

替代解决方案是将新的着色/ header 委托(delegate)直接传递到 XMLTreeViewItem 构造函数,然后递归传递到所有较低节点。这将使 XMLTreeView 保持干净的着色委托(delegate),但可能会使此类用户的自定义变得复杂,因为他们需要覆盖每个节点中的委托(delegate)。

关于c# XML Treeview (Plumbing) 收藏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14500376/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com