[我们有一个WPF应用程序,其登录页面列出了大约十二个按钮,所有按钮都将转到该类型的新视图/视图模型。它变得笨拙。我们有一个viewmodel列出了所有基本上如下所示的所有视图:
private void ExecuteViewProgramCommand()
{
OpenViewMessage message = new OpenViewMessage();
CurrentViewModel = message.ViewModel = ViewModelLocator.ProgramVM;
Messenger.Default.Send<OpenViewMessage>(message);
}
我从不喜欢这样做的方式,因为它违反了DRY原则。在第二行的上述代码中唯一发生变化的地方是,在此代码中发生什么变化的是ViewModelLocator.ProgramVM
。我的任务是重做登录页面,使登录页面更有条理,我们将添加更多启动按钮。我认为使用依赖注入会更好。另外,我正在尝试解决重新设计显示器的需求,以便将其显示在列表中,而不是按字母顺序排列在周围的按钮上。
首先,我想到了这堂课:
public class Tile
{
public string ModuleName { get; set; }
public NamedViewModelBase ModuleViewModel { get; set; }
}
((NamedViewModelBase是所有视图模型都通用的视图模型的名称。)然后我声明了一个单元测试来对其进行测试,并在单元测试中声明了它:
List<Tile> tiles = new List<Tile>()
{
new Tile()
{
ModuleName = "Program",
ModuleViewModel = ViewModelLocator.ProgramVM
},
new Tile()
{
ModuleName = "Organization",
ModuleViewModel = ViewModelLocator.OrganizationVM
}
}
但是很快就发现这是错误的。 ViewModelLocator.ProgramVM
的设置器中的分配将实例化Program的视图模型。我不希望那样,我希望有实例化它的调用,例如我们在ViewModelLocator中使用的方法:
static public ProgramViewModel ProgramVM
{
get
{
if (ServiceLocator.IsLocationProviderSet)
{
SimpleIoc ioc = ServiceLocator.Current as SimpleIoc;
return ioc.GetInstanceWithoutCaching<ProgramViewModel>(Guid.NewGuid().ToString());
}
else
{
return null;
}
}
}
因此,我想我必须更改Tile类以将ModuleViewModel属性声明为类似以下内容:public NamedViewModelBase ModuleViewModel { get; }
。但是我不知道在定义列表时如何实例化它。解决此问题的正确方法是什么?
这将是伪装的鳕鱼建议,有点像您已经在同一条轨道上:
假设BaseViewModel是所有单个VM的基类
在应用程序启动期间填写此词典(看起来像您的图块列表)
public void PreCreateVMs(){dictionary [Key] = new ConcreteViewModelType();//在这里继续添加新的Vms}
在xaml中,将所有按钮绑定到同一命令,该命令采用字符串参数(或使用Enum即兴实现)。为每个按钮传递正确的字符串键。像:单击“帐户”按钮应启动AccountVM,该帐户与“ AccountVM”键一起存储在字典中。
从维护的角度来看,添加新的ViewModel所要做的就是用新的按钮更新xaml,分配正确的命令参数字符串。使用此字符串键,然后在PreCreateVMs方法中添加正确的VM。
我已经重新设计了Tile类。我相信我需要的是第二个参数是Command。我问这是否可能会更好。这是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());
}
}
}
};
我在正确的轨道上吗?我应该将tiles
定义为词典吗?