Можете да направите това с Json.NET
рамка. Json.NET има статичен метод JToken.Parse()
(което е подобно по предназначение на XDocument.Parse()
) и може да превърне валиден JSON низ в йерархия от Newtonsoft.Json.Linq.JToken
обекти. Тази йерархия може да бъде обвързана в WPF TreeView
контролирайте с помощта на DataTemplate
и HierarchicalDataTemplate
да форматирате данни от всички възможни подкласове на JToken
и повтарят техните деца.
Конкретният Json.NET JToken
класове, за които са необходими шаблони, са:
За да свържете йерархия от тези класове в дърво, първо се нуждаете от конвертор
за да конвертирате JToken.Children()
метод в свойство:
// Respectfully adapted from https://stackoverflow.com/questions/502250/bind-to-a-method-in-wpf/844946#844946
public sealed class MethodToValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var methodName = parameter as string;
if (value == null || methodName == null)
return null;
var methodInfo = value.GetType().GetMethod(methodName, new Type[0]);
if (methodInfo == null)
return null;
return methodInfo.Invoke(value, new object[0]);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException(GetType().Name + " can only be used for one way conversion.");
}
}
След като направихме това, изключително проста XAML маркировка, която може да покаже тази йерархия в дърво, е:
<Window x:Class="WpfJsonTreeViewNew.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:w="clr-namespace:WpfJsonTreeViewNew"
xmlns:json ="clr-namespace:Newtonsoft.Json;assembly=Newtonsoft.Json"
xmlns:jlinq ="clr-namespace:Newtonsoft.Json.Linq;assembly=Newtonsoft.Json"
Title="Window1" Height="1000" Width="600">
<Window.Resources>
<w:MethodToValueConverter x:Key="MethodToValueConverter"/>
<HierarchicalDataTemplate DataType="{x:Type jlinq:JArray}" ItemsSource="{Binding Converter={StaticResource MethodToValueConverter}, ConverterParameter='Children'}">
<TextBlock Text="Array">
</TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type jlinq:JProperty}" ItemsSource="{Binding Converter={StaticResource MethodToValueConverter}, ConverterParameter='Children'}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Property name: "/>
<TextBlock Text="{Binding Path=Name, Mode=OneWay}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type jlinq:JObject}" ItemsSource="{Binding Converter={StaticResource MethodToValueConverter}, ConverterParameter='Children'}">
<TextBlock Text="Object">
</TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type jlinq:JConstructor}" ItemsSource="{Binding Converter={StaticResource MethodToValueConverter}, ConverterParameter='Children'}">
<TextBlock Text="Constructor">
</TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type jlinq:JRaw}" ItemsSource="{Binding Converter={StaticResource MethodToValueConverter}, ConverterParameter='Children'}">
<TextBlock Text="Raw">
</TextBlock>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type jlinq:JValue}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Value: "/>
<TextBox Text="{Binding Path=Value, Mode=TwoWay}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<TreeView Margin="3" Name="treeView1">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</Grid>
</Window>
След това, когато потребителят ви избере JSON данни за преглед, можете да направите:
var token = JToken.Parse(jsonString);
var children = new List<JToken>();
if (token != null)
{
children.Add(token);
}
treeView1.ItemsSource = null;
treeView1.Items.Clear();
treeView1.ItemsSource = children;
И резултатът изглежда така:
За примерния JSON :
{
""id"": ""0001"",
""type"": ""donut"",
""name"": ""Cake"",
""ppu"": 0.55,
""batters"":
{
""batter"":
[
{ ""id"": ""1001"", ""type"": ""Regular"" },
{ ""id"": ""1002"", ""type"": ""Chocolate"" },
{ ""id"": ""1003"", ""type"": ""Blueberry"" },
{ ""id"": ""1004"", ""type"": ""Devil's Food"" }
]
},
""topping"":
[
{ ""id"": ""5001"", ""type"": ""None"" },
{ ""id"": ""5002"", ""type"": ""Glazed"" },
{ ""id"": ""5005"", ""type"": ""Sugar"" },
{ ""id"": ""5007"", ""type"": ""Powdered Sugar"" },
{ ""id"": ""5006"", ""type"": ""Chocolate with Sprinkles"" },
{ ""id"": ""5003"", ""type"": ""Chocolate"" },
{ ""id"": ""5004"", ""type"": ""Maple"" }
]
}
Разбира се, потребителският интерфейс може да бъде направен по-красив, напр. като поставите стойността за JProperty
токени само с един JValue
дете на същия ред. Това обаче трябва да ви даде представа как да направите обвързването.
Този подход свързва JSON директно с дървото. Ако търсите пълна функционалност за редактиране, включително добавяне, премахване и преименуване на възли, може да искате да преминете към Методология "Model-View-ViewModel"
в който JToken
йерархията се превръща в модел, а моделът с лек изглед обработва модификациите и известията.