3

すべての XML ファイルを読み取ってツリービューに表示できる XML ビューアーを作成しています。私の目標は、XMLViewer コントロールを作成することです。ユーザーは、自分の実装で特定のルーチンを変更できる必要があります。XML ビューアが少なくともデフォルトの動作を示すように、基本的な機能を提供するデフォルトの実装を提供します。私は配管とデリゲートでこれをやろうとしています。

私がこれまでに持っているもの:

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

ご覧のとおり、ツリーノードを正しく表示するのに問題があります。これを修正するアイデアはありますか?

4

1 に答える 1

0

さて、拡張ポイントを持つツリー ビューを実装して、xml ノードのカスタム カラーリング/ヘッダーを作成しようとしています。

このために、XMLTreeViewItem ごとにいくつかのパブリック デリゲートを追加しました。呼び出し元は、独自の色/ヘッダーなどを提供するためにオーバーライドできます。

現在のソリューションの問題は、ルート ノードのみがカラーリング用のカスタム デリゲートを取得することです。ルート xml ノードが構築されると、LoadColor デリゲートのデフォルト実装を持つ新しい XMLTreeViewItem を構築することによって、すべての子がロードされます。

新しく作成された各ノードにデリゲート オーバーライドをコピーするか、デリゲートをオーバーライドしたルート ノードへの参照を保持する必要があります。

もう 1 つの問題は、XMLTreeViewItem ツリー全体がコンストラクターで生成され、デリゲートのオーバーライドが後でのみ提供されることです。

newItem = new XMLTreeViewItem(node);

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

これは、_LoadColor.Invoke を実行している時点で、ツリー全体が既に構築されており、その色が初期化されていることを意味します。_LoadColor = new LoadColorDelegate は、すべての子に渡したデリゲートを上書きし、_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 でデリゲートの色付けがなくなりますが、各ノードでデリゲートを上書きする必要があるため、このクラスのユーザーのカスタマイズが複雑になる可能性があります。

于 2013-04-11T21:43:12.943 に答える