Můžete to udělat pomocí Json.NET
rámec. Json.NET má statickou metodu JToken.Parse()
(což je svým účelem podobné jako XDocument.Parse()
) a může změnit platný řetězec JSON na hierarchii Newtonsoft.Json.Linq.JToken
objektů. Tuto hierarchii lze svázat do WPF TreeView
ovládání pomocí DataTemplate
a HierarchicalDataTemplate
k formátování dat ze všech možných podtříd JToken
a iterují prostřednictvím svých dětí.
Konkrétní JToken
Json.NET třídy, pro které jsou vyžadovány šablony, jsou:
Chcete-li svázat hierarchii těchto tříd do stromu, potřebujete nejprve převodník
převést JToken.Children()
metoda do vlastnosti:
// 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.");
}
}
Díky tomu je extrémně jednoduché označení XAML, které dokáže zobrazit tuto hierarchii ve stromu:
<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>
Poté, když uživatel vybere data JSON k zobrazení, můžete:
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;
A výsledek vypadá takto:
Pro ukázkový 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"" }
]
}
Uživatelské rozhraní by samozřejmě šlo udělat krásnější, např. umístěním hodnoty pro JProperty
tokeny pouze s jednou JValue
dítě ve stejné řadě. To by vám však mělo poskytnout představu, jak provést vazbu.
Tento přístup váže JSON přímo ke stromu. Pokud hledáte plnou funkcionalitu úprav včetně přidávání, odebírání a přejmenování uzlů, možná budete chtít přejít na metodika "Model-View-ViewModel"
ve kterém je JToken
hierarchie se stává modelem a model zjednodušeného pohledu zpracovává úpravy a upozornění.