C# MVVM中的序列化有很多问题

C# MVVM中的序列化有很多问题,c#,serialization,mvvm,C#,Serialization,Mvvm,我正在WPF中开发一个基于文本的游戏,我正在探索MVVM。目前我的项目中有两个模型,冒险家和GameDate(我现在不关心什么应该是模型,什么不应该是模型,我稍后会解决这个问题)。我有一个视图模型MainViewModel和一个视图MainView主视图具有绑定到保存/加载命令的按钮。。。这就是我被困的地方。我非常希望实现一种形式的二进制序列化;我有一个类ObjectSerializer,该类的函数和相应部分位于MainViewModel中的Save和Load命令中,但我不知道如何“获取”对需要

我正在WPF中开发一个基于文本的游戏,我正在探索MVVM。目前我的项目中有两个模型,冒险家和GameDate(我现在不关心什么应该是模型,什么不应该是模型,我稍后会解决这个问题)。我有一个视图模型
MainViewModel
和一个视图
MainView
<代码>主视图具有绑定到保存/加载命令的按钮。。。这就是我被困的地方。我非常希望实现一种形式的二进制序列化;我有一个类
ObjectSerializer
,该类的函数和相应部分位于
MainViewModel
中的Save和Load命令中,但我不知道如何“获取”对需要序列化的类(在本例中为模型)实例的访问权限,因为我从未手动实例化过任何一个类。此外,我想找到一种方法,将它们全部序列化到一个文件中(一个典型的“保存”游戏文件)

任何曾经在MVVM中处理过序列化的人都能好心地指导我完成这个过程吗?我一整天都在做这件事,却毫无进展,这让我发疯。如果有人能举个例子,我将永远欠你的债。先谢谢你,;一个能让我度过难关的答案不会不被认可。我真的在这里尝试

ObjectSerializer.cs

    protected IFormatter iformatter;

    public ObjectSerializer()
    {
        this.iformatter = new BinaryFormatter();
    }

    public T GetSerializedObject(string filename)
    {
        if (File.Exists(filename))
        {
            Stream inStream = new FileStream(
                filename,
                FileMode.Open,
                FileAccess.Read,
                FileShare.Read);
            T obj = (T)this.iformatter.Deserialize(inStream);
            inStream.Close();
            return obj;
        }
        return default(T);
    }

    public void SaveSerializedObject(T obj, string filename)
    {
        Stream outStream = new FileStream(
            filename,
            FileMode.Create,
            FileAccess.Write,
            FileShare.None);
        this.iformatter.Serialize(outStream, obj);
        outStream.Close();
    }

在处理MVVM时,模型(M)将封装在ViewModel(VM)中,并仅通过在ViewModel上显式公开的方法和属性向视图(V)公开。ViewModel将主要用作模型和视图之间的适配器。与应用程序层交互的所有逻辑(如可能需要的任何序列化)也将包含在ViewModel中,并与任何特定于UI的代码分离。这使得测试核心应用程序代码变得更容易,而不会陷入您不必关心的事情中,例如在
文本框
标签
中显示的内容。这比在
xaml.cs
文件中进行对象序列化更可取

例如:

请考虑您的
冒险家
类如下所示:

public class Adventurer { 
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Rank { get; set; } //Knight, Warlock, Whatever
}
您的
MainViewModel
可能如下所示:

public class Adventurer { 
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Rank { get; set; } //Knight, Warlock, Whatever
}
(不要担心
ViewModelBase
,只要假设在本例中,它包含了一些代码,允许您的
MainViewModel
实现
INotifyPropertyChanged
,这是使其与WPF的绑定子系统配合良好的要求)

现在您已经有了一个包装模型的基本ViewModel,一旦将UI控件设置为视图的
DataContext
,就可以轻松地将其绑定到VM上的属性

<TextBox Text="{Binding FirstName}" />
<TextBox Text="{Binding LastName}" />
<TextBox Text="{Binding Rank}" />
<Button Value="Save" Command="{Binding SaveCommand}" />
<Button Value="Load" Command="{Binding LoadCommand}" />

由于您已将ViewModel设置为包装模型,并且已将ViewModel属性正确绑定到视图,因此当用户在绑定到
FirstName
的文本框中输入值时,
\u selectedAdventurer.FirstName
中的值将使用该输入直接更新。基本上,基础模型的状态将始终与UI中显示的值同步。然后,当用户单击标记为
Save
的按钮时,将执行
Save命令
,这将触发代码,将底层的
冒险家
序列化为文件、数据库或其他任何内容


这当然是一个非常简单的示例,主要用作数据输入表单,但希望它能帮助您理解这个概念。为了更好地封装
Adventurer
绑定逻辑,您可以选择创建一个子
AdventurerViewModel
,该子
AdventurerViewModel将公开给视图,而不是将属性直接放在
MainViewModel
上。也许您需要添加一个属性
IEnumerable SavegameFiles
,您可以将其绑定到
DropDownList
,并允许用户选择要加载的文件

处理MVVM时,模型(M)将封装在ViewModel(VM)中,并仅通过在ViewModel上显式公开的方法和属性公开给视图(V)。ViewModel将主要用作模型和视图之间的适配器。与应用程序层交互的所有逻辑(如可能需要的任何序列化)也将包含在ViewModel中,并与任何特定于UI的代码分离。这使得测试核心应用程序代码变得更容易,而不会陷入您不必关心的事情中,例如在
文本框
标签
中显示的内容。这比在
xaml.cs
文件中进行对象序列化更可取

例如:

请考虑您的
冒险家
类如下所示:

public class Adventurer { 
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Rank { get; set; } //Knight, Warlock, Whatever
}
您的
MainViewModel
可能如下所示:

public class Adventurer { 
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Rank { get; set; } //Knight, Warlock, Whatever
}
(不要担心
ViewModelBase
,只要假设在本例中,它包含了一些代码,允许您的
MainViewModel
实现
INotifyPropertyChanged
,这是使其与WPF的绑定子系统配合良好的要求)

现在您已经有了一个包装模型的基本ViewModel,一旦将UI控件设置为视图的
DataContext
,就可以轻松地将其绑定到VM上的属性

<TextBox Text="{Binding FirstName}" />
<TextBox Text="{Binding LastName}" />
<TextBox Text="{Binding Rank}" />
<Button Value="Save" Command="{Binding SaveCommand}" />
<Button Value="Load" Command="{Binding LoadCommand}" />

由于您已将ViewModel设置为包装模型,并且已将ViewModel属性正确绑定到视图,因此当用户在绑定到
FirstName
的文本框中输入值时,
\u selectedAdventurer.FirstName
中的值将使用该输入直接更新。本质上,您的底层m的状态