天天看點

WPF:使用Json.NET在TreeView中樹形顯示JSON資料WPF:使用Json.NET在TreeView中樹形顯示JSON資料

原文 

<a href="http://www.cnblogs.com/mgen/archive/2013/01/04/2845015.html">據</a>

讀者可以參考這個開源的可以樹形顯示XML和JSON的工具:

<a href="http://www.cnblogs.com/mgen/archive/2013/01/16/2863430.html">Mgen Object 603:XML/JSON樹形顯示小工具</a>

或者一個更大的開源工程(建構和分析HTTP并支援XML及JSON的樹形顯示):

<a href="http://www.cnblogs.com/mgen/archive/2012/06/20/bluckbadda.html">Mgen Bluckbadda</a>

效果如下:

WPF:使用Json.NET在TreeView中樹形顯示JSON資料WPF:使用Json.NET在TreeView中樹形顯示JSON資料

(每一個項目中的左側黑字是資料的值,右側灰字是資料的類型。對于對象或數組,黑字會顯示對象的屬性個數或數組的成員個數)

具體實作方法是通過利用Json.NET中的Json對象基類:JToken類型,在Newtonsoft.Json.Linq命名空間内,這個類型的派生類型有:

WPF:使用Json.NET在TreeView中樹形顯示JSON資料WPF:使用Json.NET在TreeView中樹形顯示JSON資料

JValue類型代表着一個Json資料值,也就是不會再有子節點的原子值。

而另一個JToken的直接繼承者是JContainer類型,代表資料對象有子節點,它的派生類型:JProperty,JObject和JArray分别代表屬性,對象和數組。

我最初想到的是用JToken類型的Type屬性來建構樹,但是随後發現JTokenType的定義完全平面化,不利于不同類型成員結構的建立,于是采用直接判斷JToken對象類型的方式來建構樹。也就是直接根據不同JToken類型來生成其相應的成員節點資料。

整個樹的資料類型由一個類型來完成,名稱是JsonHeaderLogic,它定義三個屬性:

public string Header { get; private set; }

public IEnumerable&lt;JsonHeaderLogic&gt; Children { get; private set; }

public JToken Token { get; private set; }

Header是目前節點的顯示文字。

Children是子節點。(如果沒有的話值是null)

Token是原始的Json.NET中的JToken對象。

那麼在界面上,我們就可以直接使用WPF中TreeView和HierarchicalDataTemplate來這樣定義DataTemplate:

&lt;TreeView Name="treeView"&gt;

    &lt;TreeView.ItemTemplate&gt;

        &lt;HierarchicalDataTemplate ItemsSource="{Binding Children}"&gt;

            &lt;StackPanel Orientation="Horizontal"&gt;

                &lt;!-- 顯示Header屬性 --&gt;

                &lt;TextBlock Text="{Binding Header}"/&gt;

                &lt;!-- 顯示JToken的Type屬性 --&gt;

                &lt;TextBlock Text="{Binding Token.Type}" Margin="10 0 0 0" Foreground="Gray"/&gt;

            &lt;/StackPanel&gt;

        &lt;/HierarchicalDataTemplate&gt;

    &lt;/TreeView.ItemTemplate&gt;

&lt;/TreeView&gt;

JsonHeaderLogic類型的完整定義:

//+ using Newtonsoft.Json.Linq;

class JsonHeaderLogic

{

    //用于對應Json對象類型的格式化字元

    const string NULL_TEXT = "&lt;null&gt;";

    const string ARRAY = "[{0}]";

    const string OBJECT = "[{0}]";

    const string PROPERTY = "{0}";

    //用于界面綁定的屬性定義

    public string Header { get; private set; }

    public IEnumerable&lt;JsonHeaderLogic&gt; Children { get; private set; }

    public JToken Token { get; private set; }

    //内部構造函數,使用FromJToken來建立JsonHeaderLogic

    JsonHeaderLogic(JToken token, string header, IEnumerable&lt;JsonHeaderLogic&gt; children)

    {

        Token = token;

        Header = header;

        Children = children;

    }

    //外部的從JToken建立JsonHeaderLogic的方法

    public static JsonHeaderLogic FromJToken(JToken jtoken)

        if (jtoken == null)

        {

            throw new ArgumentNullException("jtoken");

        }

        var type = jtoken.GetType();

        if (typeof(JValue).IsAssignableFrom(type))

            var jvalue = (JValue)jtoken;

            var value = jvalue.Value;

            if (value == null)

                value = NULL_TEXT;

            return new JsonHeaderLogic(jvalue, value.ToString(), null);

        else if (typeof(JContainer).IsAssignableFrom(type))

            var jcontainer = (JContainer)jtoken;

            var children = jcontainer.Children().Select(c =&gt; FromJToken(c));

            string header;

            if (typeof(JProperty).IsAssignableFrom(type))

                header = String.Format(PROPERTY, ((JProperty)jcontainer).Name);

            else if (typeof(JArray).IsAssignableFrom(type))

                header = String.Format(ARRAY, children.Count());

            else if (typeof(JObject).IsAssignableFrom(type))

                header = String.Format(OBJECT, children.Count());

            else

                throw new Exception("不支援的JContainer類型");

            return new JsonHeaderLogic(jcontainer, header, children);

        else

            throw new Exception("不支援的JToken類型");

}

定義好了JsonHeaderLogic類型,在相應界面事件後使用FromJToken方法來建立JsonHeaderLogic對象然後綁定到界面TreeView控件資料源就可以了:

//建立JObject

//textfile1.txt存儲着需要解析的JSON資料

var jobj = JObject.Parse(System.IO.File.ReadAllText("textfile1.txt"));

//建立TreeView的資料源

treeView.ItemsSource = jobj.Children().Select(c =&gt; JsonHeaderLogic.FromJToken(c));

源代碼下載下傳  注意:此為微軟SkyDrive存檔,請用浏覽器直接下載下傳,用某些下載下傳工具可能無法下載下傳  示例程式運作環境:.NET Framework 4.0 Client Profile  源代碼環境:Microsoft Visual Studio Express 2012 for Windows Desktop  注意:源代碼不包含引用的外部類庫檔案: Json.NET