C# 从JSON模式创建WPF UI
有没有办法使用JSON模式创建WPF UI?我知道,在AngularJS和其他人的帮助下,可以将其转换为HTML表单。但是,寻找一种用同样的方法创建WPF的方法并没有取得成果 存在一个 介绍如何创建可视Json编辑器。我的要求与这里给出的略有不同。在我的例子中,我想基于模式和模式中提到的属性创建WPF控件。而且,在UI的帮助下,我希望能够通过在UI控件中输入值来创建尽可能多的JSON对象C# 从JSON模式创建WPF UI,c#,json,wpf,jsonschema,C#,Json,Wpf,Jsonschema,有没有办法使用JSON模式创建WPF UI?我知道,在AngularJS和其他人的帮助下,可以将其转换为HTML表单。但是,寻找一种用同样的方法创建WPF的方法并没有取得成果 存在一个 介绍如何创建可视Json编辑器。我的要求与这里给出的略有不同。在我的例子中,我想基于模式和模式中提到的属性创建WPF控件。而且,在UI的帮助下,我希望能够通过在UI控件中输入值来创建尽可能多的JSON对象 例如,让我们考虑下面的JSON模式作为示例。 { "$schema": "http://json-sch
例如,让我们考虑下面的JSON模式作为示例。
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {},
"id": "http://example.com/example.json",
"properties": {
"checked": {
"default": false,
"description": "An explanation about the purpose of this instance.",
"id": "/properties/checked",
"title": "The Checked Schema",
"type": "boolean"
},
"dimensions": {
"id": "/properties/dimensions",
"properties": {
"height": {
"default": 10,
"description": "An explanation about the purpose of this instance.",
"id": "/properties/dimensions/properties/height",
"title": "The Height Schema",
"type": "integer"
},
"width": {
"default": 5,
"description": "An explanation about the purpose of this instance.",
"id": "/properties/dimensions/properties/width",
"title": "The Width Schema",
"type": "integer"
}
},
"type": "object"
},
"id": {
"default": 1,
"description": "An explanation about the purpose of this instance.",
"id": "/properties/id",
"title": "The Id Schema",
"type": "integer"
},
"name": {
"default": "A green door",
"description": "An explanation about the purpose of this instance.",
"id": "/properties/name",
"title": "The Name Schema",
"type": "string"
},
"price": {
"default": 12.5,
"description": "An explanation about the purpose of this instance.",
"id": "/properties/price",
"title": "The Price Schema",
"type": "number"
},
"tags": {
"id": "/properties/tags",
"items": {
"default": "home",
"description": "An explanation about the purpose of this instance.",
"id": "/properties/tags/items",
"title": "The Empty Schema",
"type": "string"
},
"type": "array"
}
},
"type": "object"
}
我希望能够显示checked
属性的复选框。类似地,一个GroupBox
或带有2个TextBox
的东西控制输入尺寸(高度和宽度)。此UI应允许用户输入所需的值,根据这些值可以生成JSON对象。大概
{
"checked": false,
"dimensions": {
"width": 5,
"height": 10
},
"id": 1,
"name": "A green door",
"price": 12.5,
"tags": [
"home",
"green"
]
}
目前,我正在创建一个JSchema
对象列表,并将每个属性反序列化为JSchema
类型,然后将其添加到列表中。此后,我将尝试为相同的对象创建控件。这真是一团糟,我还没有完全达到我的目标。然而,我并不认为我会对最终结果感到满意。如果你能提出一个实现同样目标的方法,那将是非常有帮助的。谢谢
从
因此,这当然是可能的。您需要做的是定义反序列化例程,使实现
inotifypropertychanged
的List/ObservableCollection
对象。您可以通过newtonsoftjson
或编写JSchema
到ViewModel
转换器来实现这一点
接下来,您可以将ContentControl
甚至Listbox/StackPanel
绑定到此可枚举对象,就像主详细视图一样,并且详细视图可以在选定对象上实现属性网格
确保所有绑定都是双向的,以保留所做的更改。
此外,您可以在StackPanel
上实现OnSelectionChanged
事件来序列化更改
资源
我想为UWP做同样的事情,但没有找到一个可行的解决方案。
除了上面提到的PropertyGrid,我还发现
来自Windows社区工具包和Telerik。
使用这些仍然需要将Json转换为对象模型并返回。
事实证明,Newtonsoft.Json是在考虑数据绑定的情况下构建的,因此从Json生成绑定到Json属性的控件非常容易。
下面是一段代码片段:
private void RenderForm(JArray jArray)
{
StackPanel stackPanel = new StackPanel() { Orientation = Orientation.Vertical };
this.Content = stackPanel;
stackPanel.Height = this.Height;
stackPanel.Width = this.Width;
stackPanel.Children.Add(button);
foreach (JObject element in jArray)
{
String type = element["type"].ToString();
TextBlock textBlock = new TextBlock() { Text = element["name"].ToString() };
textBlock.Padding = new Thickness() { Top = 5 };
switch (type)
{
case "hiddendata":
break;
case "bool":
CheckBox checkBox = new CheckBox();
checkBox.DataContext = element;
Binding checkBoxBinding = new Binding() { Path = new PropertyPath("[value].Value"), Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };
checkBoxBinding.Source = element;
checkBox.SetBinding(CheckBox.IsCheckedProperty, checkBoxBinding);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(checkBox);
break;
case "image":
if (!String.IsNullOrEmpty(element["value"].Value<String>()))
{
Image image = new Image();
image.MaxHeight = 200;
image.MaxWidth = 200;
var ignore = SetImageSource(element["value"].Value<String>(), image);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(image);
}
break;
case "info":
if (!String.IsNullOrEmpty(element["value"].Value<String>()))
{
TextBlock displayTextBlock = new TextBlock();
displayTextBlock.DataContext = element;
Binding displayTextBlockBinding = new Binding() { Path = new PropertyPath("[value].Value"), Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };
displayTextBlockBinding.Source = element;
displayTextBlock.SetBinding(TextBlock.TextProperty, displayTextBlockBinding);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(displayTextBlock);
}
break;
case "password":
PasswordBox passwordBox = new PasswordBox();
passwordBox.DataContext = element;
Binding passwordBoxBinding = new Binding() { Path = new PropertyPath("[value].Value"), Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };
passwordBoxBinding.Source = element;
passwordBox.SetBinding(PasswordBox.PasswordProperty, passwordBoxBinding);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(passwordBox);
break;
case "string":
default:
TextBox textBox = new TextBox();
textBox.DataContext = element;
Binding textBoxBinding = new Binding() { Path = new PropertyPath("[value].Value"), Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged };
textBoxBinding.Source = element;
textBox.SetBinding(TextBox.TextProperty, textBoxBinding);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(textBox);
break;
}
}
}
private void RenderForm(JArray-JArray)
{
StackPanel StackPanel=new StackPanel(){Orientation=Orientation.Vertical};
this.Content=stackPanel;
stackPanel.Height=此.Height;
stackPanel.Width=此.Width;
stackPanel.Children.Add(按钮);
foreach(jArray中的JObject元素)
{
字符串类型=元素[“类型”]。ToString();
TextBlock TextBlock=new TextBlock(){Text=element[“name”].ToString()};
textBlock.Padding=新厚度(){Top=5};
开关(类型)
{
案例“隐藏数据”:
打破
案例“bool”:
复选框=新复选框();
checkBox.DataContext=element;
Binding checkBoxBinding=new Binding(){Path=new PropertyPath(“[value].value”),Mode=BindingMode.TwoWay,UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged};
checkBoxBinding.Source=元素;
checkBox.SetBinding(checkBox.IsCheckedProperty,checkBoxBinding);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(复选框);
打破
案例“图像”:
如果(!String.IsNullOrEmpty(元素[“value”].value()))
{
图像=新图像();
image.MaxHeight=200;
image.MaxWidth=200;
var ignore=SetImageSource(元素[“值”].value(),图像);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(图像);
}
打破
案例“信息”:
如果(!String.IsNullOrEmpty(元素[“value”].value()))
{
TextBlock displayTextBlock=新建TextBlock();
displayTextBlock.DataContext=元素;
Binding displayTextBlockBinding=new Binding(){Path=new PropertyPath(“[value].value”),Mode=BindingMode.OneWay,UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged};
displayTextBlockBinding.Source=元素;
displayTextBlock.SetBinding(TextBlock.TextProperty,displayTextBlockBinding);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(displayTextBlock);
}
打破
案例“密码”:
PasswordBox PasswordBox=new PasswordBox();
passwordBox.DataContext=元素;
Binding passwordBoxBinding=new Binding(){Path=new PropertyPath(“[value].value”),Mode=BindingMode.TwoWay,UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged};
passwordBoxBinding.Source=元素;
设置绑定(passwordBox.PasswordProperty,passwordBoxBinding);
stackPanel.Children.Add(textBlock);
stackPanel.Children.Add(密码箱);
打破
大小写“字符串”:
违约:
TextBox TextBox=新建TextBox();
textBox.DataContext=元素;
Binding textBoxBinding=新绑定(){Path=