【问题标题】:How to display JSON in WPF TreeView如何在 WPF TreeView 中显示 JSON
【发布时间】:2018-03-30 19:17:13
【问题描述】:

我正在阅读 JSON,然后在 WPF 树视图中显示它。

这里是代码...

Class MainWindow
Public Sub New()

    InitializeComponent()
    Dim dic = GetThreadedObject(GetJASN())("phases")
    Dim items = dic(0)
    tView.ItemsSource = items

End Sub

Private Function GetJASN() As String
    Dim output As String = My.Computer.FileSystem.ReadAllText(My.Application.Info.DirectoryPath & "\UAL525 Phase of Flight.json")
    Return output
End Function

Private Function GetThreadedObject(JASN As String)
    Dim Js As New JavaScriptSerializer()
    Js.MaxJsonLength = JASN.Length * 2
    Dim j = Js.Deserialize(Of Object)(JASN)
    Return j
End Function
End Class

还有 WPF...

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
    <TreeView x:Name="tView">

    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Value}" >
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" Foreground="Red"/>
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
            <TextBlock Text="{Binding Key}"/>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>

</TreeView>
</Grid>

起点和终点(上图)看起来不错(可能是因为它们包含要显示的子元素)。

但是 Phase 元素应该只包含一个值。读取“GROUND”的单个字符串。但由于某种原因,它被分解成一个 charArray。并在多个元素中显示如上图。

那么解决这个问题的关键是什么?显示字符串与其他对象不同的多个数据模板?

【问题讨论】:

    标签: json wpf hierarchicaldatatemplate


    【解决方案1】:

    问题是您的 XAML 只能显示字典值中的集合,如果有 string,那么它将被视为字符集合。快速解决方案之一是创建一个转换器,它将您的字符串转换为字符串集合。

    为此,您需要一个值转换器(对不起,我在 c# 中编写代码)

    public class ValConv : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is string str)
            {
                return new List<string> { str };
            }
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
    }
    


    在资源中实例化这个转换器:

    <Window.Resources>
    <local:ValConv x:Key="valKonv"/>
    </Window.Resources>
    


    并使用它:

    <HierarchicalDataTemplate ItemsSource="{Binding Value, Converter={StaticResource valConv}}" >
    

    【讨论】:

    • 感谢您的回答。让 Vb 转换工作需要一些工作,但我明白了。
    【解决方案2】:

    这是 Rekshino 提交的 Vb 代码。

    Imports System.Globalization
    Public Class ValConv
    Implements IValueConverter
    Private Function IValueConverter_Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
        If (TypeOf value Is String) Then
            Dim newStr As New List(Of String)
            newStr.Add(value)
            Return newStr
        Else
            Return value
        End If
    End Function
    
    Private Function IValueConverter_ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
        Return value
    End Function
    

    结束类

    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp2"
        Title="Window1" Height="300" Width="300">
    
    <Window.Resources>
        <local:ValConv x:Key="valConv"/>
    </Window.Resources>
    <Grid>
        <TreeView x:Name="tView">
    
        <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Value, Converter={StaticResource valConv}}" >
                    <HierarchicalDataTemplate.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}" Foreground="Red"/>
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>
                <TextBlock Text="{Binding Key}"/>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    
    </TreeView>
    </Grid>
    

    【讨论】:

      【解决方案3】:

      我需要一个更通用的操作来使用任何 JSON。

      此代码使用 nuget Newtonsoft JSON 来执行获取任何原始 JSON(无模型)并将其加载到如下所示的 TreeView 中的魔力:

      JSON

      string jsonString = @"[{""BatchId"":0,""AccessionChanges"":[{""LabId"":8675309,""InstanceChanges"":[{""Property"":""Note"",""ChangedTo"":""Jabberwocky"",""UniqueId"":null,""SummaryInstance"":null},{""Property"":""Instrument"",""ChangedTo"":""instrumented"",""UniqueId"":null,""SummaryInstance"":null}],""DetailChanges"":[{""Property"":""Comments"",""ChangedTo"":""2nd Comment"",""UniqueId"":null,""SummaryInstance"":null},{""Property"":""CCC"",""ChangedTo"":""XR71"",""UniqueId"":null,""SummaryInstance"":null}]}]}]";

      Xaml &lt;TreeView x:Name="tView" /&gt;

      Codbehind Xaml

      InitializeComponent();
      try
      {
          tView.Items.Add(JSONOperation.Json2Tree(JArray.Parse(jsonString), "Root"));    
      }
      catch (JsonReaderException jre)
      {
          MessageBox.Show($"Invalid Json {jre.Message}");
      }
      

      公共静态类 JSONOperation

      public static TreeViewItem Json2Tree(JToken root, string rootName = "")
      {
          var parent = new TreeViewItem() { Header = rootName };
      
          foreach (JToken obj in root)
              foreach (KeyValuePair<string, JToken> token in (JObject)obj)
                  switch (token.Value.Type)
                  {
                      case JTokenType.Array:
                          var jArray = token.Value as JArray;
      
                          if (jArray?.Any() ?? false)
                              parent.Items.Add(Json2Tree(token.Value as JArray, token.Key));
                          else
                              parent.Items.Add($"\x22{token.Key}\x22 : [ ]"); // Empty array   
                          break;
      
                      case JTokenType.Object:
                          parent.Items.Add(Json2Tree((JObject)token.Value, token.Key));
                          break;
      
                      default:
                          parent.Items.Add(GetChild(token));
                          break;
                  }
      
          return parent;
      }
      
      private static TreeViewItem GetChild(KeyValuePair<string, JToken> token)
      {
          var value = token.Value.ToString();
          var outputValue = string.IsNullOrEmpty(value) ? "null" : value;
          return new TreeViewItem() { Header = $" \x22{token.Key}\x22 : \x22{outputValue}\x22"}; 
      }
      

      【讨论】:

      • 缺少括号和分号:return new TreeViewItem{ Header = $" \x22{token.Key}\x22 : \x22{outputValue}\x22"};
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-08
      • 1970-01-01
      • 2016-05-29
      • 2017-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多