C# 想要一种方法来编写一个具有属性的类,该属性将返回ViewModel的新实例吗

C# 想要一种方法来编写一个具有属性的类,该属性将返回ViewModel的新实例吗,c#,wpf,mvvm-light,C#,Wpf,Mvvm Light,我们有一个WPF应用程序,它有一个登录页,上面列出了十几个左右的按钮,所有这些按钮都指向这种类型的新视图/视图模型。它变得笨重了。我们有一个viewmodel,它列出了所有这些基本上如下所示: private void ExecuteViewProgramCommand() { OpenViewMessage message = new OpenViewMessage(); CurrentViewModel = message.ViewModel

我们有一个WPF应用程序,它有一个登录页,上面列出了十几个左右的按钮,所有这些按钮都指向这种类型的新视图/视图模型。它变得笨重了。我们有一个viewmodel,它列出了所有这些基本上如下所示:

    private void ExecuteViewProgramCommand()
    {
        OpenViewMessage message = new OpenViewMessage();
        CurrentViewModel = message.ViewModel = ViewModelLocator.ProgramVM;
        Messenger.Default.Send<OpenViewMessage>(message);
    }
NamedViewModelBase是所有viewmodels通用的viewmodel的名称。然后我声明了一个单元测试来测试这一点,并在单元测试中声明了这一点:

List<Tile> tiles = new List<Tile>()
{
    new Tile()
    {
        ModuleName = "Program",
        ModuleViewModel = ViewModelLocator.ProgramVM
    },
    new Tile()
    {
        ModuleName = "Organization",
        ModuleViewModel = ViewModelLocator.OrganizationVM
    }
}

因此,我认为我必须更改Tile类,以将ModuleViewModel属性声明为如下内容:public NamedViewModelBase ModuleViewModel{get;}。但我不知道在定义列表时如何实例化它。解决这一问题的正确方法是什么?

这将是一个psuedo codish建议,它与您现在所处的轨道相同:

假设BaseViewModel是所有单个VM的基类

创建字典 在应用程序启动时填写此词典看起来像是您的平铺列表

公共无效预创建VM { dictionary[Key]=新的ConcreteViewModelType; //继续在这里添加新的虚拟机 }

在xaml中,将所有按钮绑定到接受字符串参数的同一个命令,或者使用Enum临时创建该命令。为每个按钮传递正确的字符串键。 类似:Accounts按钮单击应启动AccountVM,它与AccountVM键一起存储在字典中

在命令处理程序-使用字符串,查找字典,找到正确的ViewModel并将此对象分配给CurrentViewModel
从维护的角度来看,添加新的ViewModel所需的只是使用新按钮更新xaml,并指定正确的命令参数字符串。使用这个字符串键并在PreCreateVMs方法中添加正确的VM。

我已经重新设计了Tile类。我认为我需要的是第二个参数是一个命令。我在问这是否会更好。下面是Tile的新定义以及我如何尝试实现它的示例:

public class Tile
{
    public string ModuleName { get; set; }
    //public NamedViewModelBase ModuleViewModel { get; set; }
    public Action ThisCommand { get; set; }
}
下面是我如何将其作为一个列表来实现的:

List<Tile> tiles = new List<Tile>()
{
    new Tile()
    {
        ModuleName = "Program",
        ThisCommand = () => 
        {
            if (ServiceLocator.IsLocationProviderSet)
            {
                SimpleIoc ioc = ServiceLocator.Current as SimpleIoc;
                ioc.GetInstanceWithoutCaching<ProgramViewModel>(Guid.NewGuid().ToString());
            }
        }
    },
    new Tile()
    {
        ModuleName = "Organization",
        ThisCommand = () =>
        {
            if (ServiceLocator.IsLocationProviderSet)
            {
                SimpleIoc ioc = ServiceLocator.Current as SimpleIoc;
                ioc.GetInstanceWithoutCaching<OrganizationViewModel>(Guid.NewGuid().ToString());
            }
        }
    }
};

我走对了吗?我应该将tile定义为字典吗?

如果您的虚拟机具有最小的ctor,没有db调用等,那么只需初始化,您就可以创建它们的observeCollection,并指定一个buttton作为listview使用的模板,并以这种方式呈现它们。我知道IoC给人的印象是自动解决方案,但它实际上只是一组美化的全局变量。你的问题有点不清楚。给定当前的平铺实现,可以将其ModuleViewModel属性设置为任何视图模型。你的问题到底是什么?问题是,如果用户在程序上单击3次,他们总是会得到一个新的ProgramViewModel实例。按照我实现Tile类的方式,它们将得到相同的实例,这是我不允许的。如果我演示如何实例化一个新的VM,比如ProgramVM,可能是最好的。以下代码来自ViewModelLocator:静态公共程序ViewModel程序VM{get{if ServiceLocator.IsLocationProviderSet{SimpleIoc ioc=ServiceLocator.Current as SimpleIoc;返回ioc.GetInstanceWithout CachingGuid.NewGuid.ToString;}否则{return null;}}
public class Tile
{
    public string ModuleName { get; set; }
    //public NamedViewModelBase ModuleViewModel { get; set; }
    public Action ThisCommand { get; set; }
}
List<Tile> tiles = new List<Tile>()
{
    new Tile()
    {
        ModuleName = "Program",
        ThisCommand = () => 
        {
            if (ServiceLocator.IsLocationProviderSet)
            {
                SimpleIoc ioc = ServiceLocator.Current as SimpleIoc;
                ioc.GetInstanceWithoutCaching<ProgramViewModel>(Guid.NewGuid().ToString());
            }
        }
    },
    new Tile()
    {
        ModuleName = "Organization",
        ThisCommand = () =>
        {
            if (ServiceLocator.IsLocationProviderSet)
            {
                SimpleIoc ioc = ServiceLocator.Current as SimpleIoc;
                ioc.GetInstanceWithoutCaching<OrganizationViewModel>(Guid.NewGuid().ToString());
            }
        }
    }
};