【发布时间】:2017-12-04 13:27:34
【问题描述】:
我正在尝试创建一个数据网格,它的条目具有来自 json 的属性。问题是很多属性应该是根据json中的信息动态生成的。
我尝试的第一件事是用自己的 getter 和 setter 列出所有可能的属性。但这是一个很长的列表,感觉应该有一个自动化的解决方案来解决这个问题。这包含在 Datagrid 条目视图模型的末尾。所以我可以在以下情况下绑定到 Number:
Number = obj.NUMBER;
之后我研究了动态类型和expandoObjects。我了解到,显然不可能将 WPF 绑定到 expandoObject 的扩展属性。所以我无法绑定到 expando.Number
expando.Number = obj.NUMBER
我还尝试遵循 this 示例,其中创建了帮助类以帮助绑定,但我似乎无法让它工作。当我运行我的解决方案时,我收到一条错误消息,指出属性“Numberz”不存在。所以我无法绑定到 Numberz:
AddProperty("Numberz", typeof(string));
SetPropertyValue("Numberz", obj.NUMBER);
目前我没有想法,所以如果这里有人可以提供帮助,我将非常感激。也许是一些最后的笔记。我不是一个非常有经验的程序员,我正在尝试通过 MVVM 模式工作。
数据网格入口视图模型
公共类 DatagridEntryViewModel : ICustomTypeProvider, INotifyPropertyChanged { #region 字段
/// <summary>
/// Custom Type provider implementation - delegated through static methods.
/// </summary>
private readonly CustomTypeHelper<DatagridEntryViewModel> _helper = new CustomTypeHelper<DatagridEntryViewModel>();
#endregion
#region Constructor
public DatagridEntryViewModel(ExitCoil model)
{
_helper.PropertyChanged += (s, e) => PropertyChanged(this, e);
dynamic Json = JObject.Parse(model.JsonCoilData);
//CreationDatePost = Json.CREATION_DATE_S_POST;
////Number = Json.NUMBER;
//CreationDatePost = Json.CREATION_DATE_S_POST;
////LeverageOrder = Json.LEVERAGE_ORDER;
//Client = Json.CLIENT;
//Skinned = Json.SKINNED;
dynamic expando = new ExpandoObject();
dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(Json.ToString());
//AddProperty("Numberz", typeof(string));
//SetPropertyValue("Numberz", obj.NUMBER);
//expando.AddItem("Number");
//expando[0] = obj.NUMBER;
//Number = expando.Number;
Model = model;
//var settings = new JsonSerializerSettings();
//settings.Converters.Add(new Models.DynamicJsonConverter());
//var serializer = JsonSerializer.Create(settings);
//JsonReader reader = new JsonTextReader(new StringReader(JsonString));
//var Data = serializer.Deserialize<DynamicObject>(reader);
}
#endregion
#region Model & proxy
private ExitCoil _model;
public ExitCoil Model
{
set { _model = value; }
}
#endregion
#region Public Methods
// Methods to support dynamic properties.
public static void AddProperty(string name)
{
CustomTypeHelper<DatagridEntryViewModel>.AddProperty(name);
}
public static void AddProperty(string name, Type propertyType)
{
CustomTypeHelper<DatagridEntryViewModel>.AddProperty(name, propertyType);
}
public static void AddProperty(string name, Type propertyType, List<Attribute> attributes)
{
CustomTypeHelper<DatagridEntryViewModel>.AddProperty(name, propertyType, attributes);
}
public void SetPropertyValue(string propertyName, object value)
{
_helper.SetPropertyValue(propertyName, value);
}
public object GetPropertyValue(string propertyName)
{
return _helper.GetPropertyValue(propertyName);
}
public PropertyInfo[] GetProperties()
{
return _helper.GetProperties();
}
Type ICustomTypeProvider.GetCustomType()
{
return _helper.GetCustomType();
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region Properties
//public string Number { get; private set; }
//public string CreationDatePost { get; private set; }
//public string LeverageOrder { get; private set; }
public string Client { get; private set; }
//public int OrderZnTop { get; private set; }
//public int OrderZnBottom { get; private set; }
//public string OrderAspect { get; private set; }
//public string OderSideTrimming { get; private set; }
//public string OrderPassivation { get; private set; }
//public string OrderOilType { get; private set; }
//public string OrderOilQuantity { get; private set; }
#endregion
}
数据网格视图模型
public class DatagridViewModel : MainViewModelBase
{
#region Singleton
public static DatagridViewModel Instance = new DatagridViewModel();
#endregion
#region Fields
private ObservableCollection<DatagridEntryViewModel> _coilEntries = new ObservableCollection<DatagridEntryViewModel>();
private readonly IViewManager _viewManager;
private readonly IDockManager _dockManager;
#endregion
#region Properties
public ObservableCollection<DatagridEntryViewModel> CoilEntries
{
get { return _coilEntries; }
set
{
_coilEntries = value;
RaisePropertyChanged(() => CoilEntries);
}
}
public ProductionExitCoilReport Report { get; set; }
#endregion
#region Constructor
public DatagridViewModel()
{
_viewManager = Globals.Container.Resolve<IViewManager>();
_dockManager = Globals.Container.Resolve<IDockManager>();
getReport();
foreach (var Coil in Report.Coils)
{
CoilEntries.Add(new DatagridEntryViewModel(Coil));
}
}
#endregion
#region Methods
public void getReport()
{
var proxy = new Proxy<IReportService>();
proxy.Open();
var LijnId = new LijnIdentificatie { Department = "HDG", Firm = "LIE", LineNumber = "05" };
var Periode = new Period { FromDate = new DateTime(2017 - 11 - 10), FromShift = 1, ToDate = new DateTime(2017 - 11 - 10), ToShift = 1 };
var request = new ProductionReportRequest() { LijnIdentificatie = LijnId, Period = Periode };
Report = proxy.Service.GetProductionExitCoilReport(request);
}
#endregion
}
数据网格 XAML
<DataGrid x:Class="Promo.Presentation.Views.CoilGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/marukp-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Promo.Presentation.Views"
xmlns:components="clr-namespace:Promo.Presentation.Components"
xmlns:Data="clr-namespace:Promo.Presentation.ViewModels"
AutoGenerateColumns="False"
GridLinesVisibility="none"
Background="White"
Height="Auto"
Width="Auto"
MinWidth="500"
MinHeight="500"
DataContext="{x:Static Data:DatagridViewModel.Instance}"
ItemsSource="{Binding CoilEntries}"
IsReadOnly="True"
HeadersVisibility="Column"
Padding="10"
>
<DataGrid.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Styles/Colors.xaml"/>
<ResourceDictionary Source="../Styles/Datagrid.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Numberz}" Header="Rolnummer" MaxWidth="125"/>
<DataGridTextColumn Binding="{Binding CreationDatePost}" Header="Post" MaxWidth="200"/>
<DataGridTextColumn Binding="{Binding LeverageOrder}" Header="Leverage order" MaxWidth="200"/>
<DataGridTextColumn Binding="{Binding Client}" Header="Client" MaxWidth="400"/>
<DataGridTextColumn Binding="{Binding OrderZnTop}" Header="Order zinc top" MaxWidth="200"/>
<DataGridTextColumn Binding="{Binding OrderZnBottom}" Header="Order zinc bottom" MaxWidth="200"/>
<DataGridTextColumn Binding="{Binding OrderAspect}" Header="Order aspect" MaxWidth="125"/>
<DataGridCheckBoxColumn Binding="{Binding OrderSideTrimming, Converter={local:StringToBoolConverter}}" Header="Order Side Trimming" MaxWidth="200"/>
<DataGridTextColumn Binding="{Binding OrderPassivation}" Header="Order Passivation" MaxWidth="200"/>
<DataGridCheckBoxColumn Binding="{Binding Skinned, Converter={local:StringToBoolConverter}}" Header="Skinned" MaxWidth="200"/>
</DataGrid.Columns>
</DataGrid>
Json 的一部分
{"NUMBER":"G571015110","CREATION_DATE_S_POST":"2017-05-11T00:00:00""LEVERAGE_ORDER":"FD72BIGA5W/8","CLIENT":"ARCELORMITTAL BELGIUM SA"}
【问题讨论】:
-
请仔细阅读整个问题@ASh。我的是我的行具有动态属性,而不是表本身的列。
-
我确实阅读了整个问题,但缺少一些重要的信息。 json 结构的示例将有所帮助。 DataGrid 为每个条目属性生成一个列,因此动态属性对我来说意味着动态列
-
那就这样说,而不是说它是重复的。无论如何,我现在已经添加了额外的信息。
-
如果你有一个包含所有属性的 json,那么 Visual Studio 可以为你生成类!无需自己创建它们。我过去曾处理过类似的情况,之前已经做过:-)。查看基于 json 在 Visual Studio 中生成类。这应该会让你更容易一些。