提问人:Justinas Rubinovas 提问时间:10/31/2023 更新时间:10/31/2023 访问量:57
用于 WPF 绑定的对象的序列化/反序列化
Serialization/deserialization of an object that is used for WPF binding
问:
在我的应用程序中,我有一个数据结构,用于保存用户输入和其他信息,其中大部分数据用于 MVVM WPF 绑定。此结构具有嵌套类、自定义对象的实例、列表等。您不必通读所有内容,但这只是其中的摘录:
public class StudyData
{
public StudyInputData InputData { get; init; } = new();
public class StudyInputData : StudyDataCategory
{
public VesselData Vessel { get; init; } = new();
public EnvironmentData Environment { get; init; } = new();
public VesEnvInteractionData Interaction { get; init; } = new();
public class VesselData : StudyDataCategory
{
public BuoyancyScope buoyancyScope { get; init; } = new();
public LoadingCondition loadingCondition { get; init; } = new();
public Resistance resistance { get; init; } = new();
public class BuoyancyScope : StudyDataCategory
{
public StudyInputDataPropertyICadObjectInfos BuoyancyScopeCadObjectsIncluded { get; init; } = new(StudyInputDataPropertyNames.BuoyancyScopeCadObjectsIncluded);
public StudyInputDataPropertyICadObjectInfos BuoyancyScopeCadObjectsExcluded { get; init; } = new(StudyInputDataPropertyNames.BuoyancyScopeCadObjectsExcluded);
}
public class Resistance : StudyDataCategory
{
public StudyInputDataPropertyString resistanceAlgorithmName { get; init; } = new("Resistance algorithm", defaultValue: Utils.GetEnumDescription(ResistanceAlgorithmNames.kaper));
}
}
public class EnvironmentData : StudyDataCategory
{
public StudyInputDataPropertyString UpperMediumMaterial { get; init; } = new(StudyInputDataPropertyNames.UpperMediumMaterial) { Value = "Air" };
public StudyInputDataPropertyString LowerMediumMaterial { get; init; } = new(StudyInputDataPropertyNames.LowerMediumMaterial) { Value = "Fresh water" };
public StudyInputDataPropertyMultiNumeric GravityConstant { get; init; } = new(StudyInputDataPropertyNames.LowerMediumMaterial) { InputString = "9.81" };
}
public class VesEnvInteractionData : StudyDataCategory
{
public Immersion immersion { get; init; } = new();
public ForcesMoments forcesMoments { get; init; } = new();
public class Immersion : StudyDataCategory
{
public StudyInputDataPropertyBool CalculateImmersion { get; init; } = new(StudyInputDataPropertyNames.CalculateImmersion, defaultValue = false);
public StudyInputDataPropertyMultiNumeric Draft { get; init; } = new(StudyInputDataPropertyNames.Draft);
public StudyInputDataPropertyMultiNumeric Heel { get; init; } = new(StudyInputDataPropertyNames.Heel, defaultInputString: "0");
public StudyInputDataPropertyMultiNumeric Trim { get; init; } = new(StudyInputDataPropertyNames.Trim, defaultInputString: "0");
}
public class ForcesMoments : StudyDataCategory
{
public ObservableCollection<IStudyInputDataPropertyForce> Forces { get; init; } = new()
{
new StudyInputDataPropertyWeightForce("Weight force"),
new StudyInputDataPropertyLiftingForce("Lifting"),
new StudyInputDataPropertyDrivingForce("Driving force"),
new StudyInputDataPropertyWindageForce("Windage")
};
}
}
}
}
请注意,这些对象中的最终基元类型变量要么实现 ,要么属于使绑定工作的类型。INotifyPropertyChanged
ObservableCollection
我想通过在用户进行一些修改后序列化为 JSON 文件来实现文件另存为 / 文件打开功能,然后将其反序列化回来,完全按原样进行反序列化,而不会破坏 WPF 绑定。StudyData
目前,我正在使用 JSON 反序列化来完全替换 的实例,它提供了 100% 保证反序列化的对象与序列化的对象完全相同,但这会破坏 WPF 绑定,因为 仍然引用 的旧实例。为了解决这个问题,我必须在反序列化后手动更新每个 UI 元素,或者使用奇怪的恶作剧绑定代码隐藏,例如:StudyData
DataContext
StudyData
DataContext
StudyData
string path = "study.Data.InputsData.Interaction.Immersion.CalculateImmersion.Value"
Binding binding = new Binding() { Path = new PropertyPath(path) };
item.SetBinding(ImmersionCalculationEnabledCheckBox.IsChecked, binding);
此解决方法有其局限性,例如无法绑定到用户可能已添加到该列表的列表元素,因为它不是不同的属性等。我也知道这不是 MVVM,总体上不是一个好的编码实践。
有人告诉我,我可以使用 DTO 进行序列化,以将 UI 绑定问题与序列化问题分开。我对 DTO 进行了一些研究,因为它对我来说是一个新概念,据我了解,我必须将每个属性从实例显式映射到 DTO。这对我来说似乎真的无法维护,因为有几千个变量,每次我添加/更改此数据结构时,我都必须手动更新 DTO。StudyData
StudyData
我正在考虑的另一个想法是将 JSON 反序列化为 的单独实例,然后使用 Reflection 传输端点基元类型变量的值,这与 DTO 的想法基本相同,而无需手动映射所有内容。但是,我不知道如何以一种与结构无关的自动化方式做到这一点,这在开发过程中可能仍然会发生很大变化。StudyData
StudyInputData
我发现的另一个想法是使用 ,这不应该破坏绑定,但显然它不适用于 AND 正如我需要的那样,因为它会将反序列化的项目添加到列表中而不是替换它们,从而导致重复。JsonConvert.PopulateObject
List
ObservableCollection
TLDR:我觉得我错过了一些用于这种情况的简单佳能解决方案。我的要求很简单:以全自动且免维护的方式序列化和反序列化数据结构,这种方式与内部结构和复杂性无关,并且在反序列化后生成相同的对象,而不会破坏 WPF 绑定。StudyData
StudyData
谁能建议我应该在这里做什么?
答: 暂无答案
评论
StudyData