当虚拟机(以及视图)需要接受其对象被异步初始化的构造函数参数时,如何在Views/ViewModels之间切换。或者,还有更好的方法可以为视图/虚拟机提供这些对象吗?如何切换所提供的提前异步初始化的对象的Views/ViewModels?
这是我以前的实现当View/VM没有使用构造函数参数。
MainWindow.xaml
用途的DataTemplates到景观当ContentControl中的变化之间切换。
<Window.DataContext>
<viewModels:MainWindowViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type viewModels:InitializerViewModel}">
<userControls:InitializerUserControl />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:GameListingViewModel}">
<views:GameListingView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:StreamListingViewModel}">
<views:StreamListingView />
</DataTemplate>
</Window.Resources>
<ContentControl x:Name="ContentSection" Content="{Binding CurrentViewModel, Mode=OneWay}">
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="Loaded">
<interactivity:InvokeCommandAction Command="{Binding StartInitializationCommand}"/>
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
</ContentControl>
MainWindowViewModel.cs
创建新的ViewModels,然后设置CurrentViewModel到相关的视图模型。当此变化时,DataTemplate基于上述数据模板切换视图。
public class MainWindowViewModel : BaseViewModel
{
private InitializerViewModel _initializerViewModel;
public ICommand StartInitializationCommand { get; set; }
public MainWindowViewModel()
{
StartInitializationCommand = new AwaitableDelegateCommand(InitializeAsync);
}
private async Task InitializeAsync()
{
_initializerViewModel = new InitializerViewModel();
CurrentViewModel = _initializerViewModel;
var initializationResult = await _initializerViewModel.InitializeAsync();
if (initializationResult)
{
GameListingViewModel = new GameListingViewModel(_initializerViewModel.MyObject1, _initializerViewModel.MyObject2);
CurrentViewModel = GameListingViewModel;
}
}
}
GameListingView.xaml(这是虚拟机我进出开关中的一个):
以前在其XAML经由定义的DataContext:
<UserControl.DataContext>
<viewModels:GameListingViewModel />
</UserControl.DataContext>-->
所有上述作品的如预期。
现在,由于新的功能,这些需要的ViewModels才能正常接收1个或多个对象,所以我想他们传递到构造函数。因此,我不能再在xaml中定义DataContext,但我可以使用代码隐藏来创建它们。
public GameListingView(ConfigSettings configSettings, GameBoxHelper gameBoxHelper)
{
InitializeComponent();
DataContext = new GameListingViewModel(configSettings, gameBoxHelper);
}
的问题是这需要查看的构造也采取了相关的对象(否则,我会得到这些对象的?),这使得DataTemplate中回MainWindow.xaml
不再起作用。
Xaml错误消息:“类型'GameListingView'不能用作对象元素,因为它不是公共的,或者没有定义一个公共的无参数构造函数或类型转换器,没有找到默认构造函数。
重要的是,将被传递到这些的ViewModels的对象都没有准备好立即; MainWindowViewModel会事先对它们进行初始化,这是以异步方式完成的。根据上面的错误信息,我认为可以使用TypeConverter
(将待传递的对象绑定到参数并将它们作为TypeConverter的参数指定给xaml),但我不明白这是如何工作的,因为它们不是立即准备就绪(异步初始化)。
仅供参考:目的是当应用程序加载完成时,所有初始化都会在前面完成(从文件系统读取配置设置,从Web APIs中检索一些数据等),以便在需要时立即做好准备应用程序的其他部分响应更快。我不希望将对象的异步初始化移动到使用它们的虚拟机。
我没有使用任何MVVM框架。
考虑到这一切,我的问题是如何继续切换视图/虚拟机,同时提供它们提前异步初始化的对象?
我认为你可以在视图中使用DependancyProperty和更新每当更改视图模型。 – Ron
你能提供一个例子说明如何工作吗? – JBC
考虑以视图模型为中心的设计,其中您的主视图模型具有子视图模型(或子视图模型集合)作为属性,并且子视图模型可具有其自己的子VM属性。使用'DataTemplate'来隐式地将视图分配给视图模型,而不是视图创建自己的视图模型。 ''ContentControl Content =“{Binding BlahVM}”/>' - 无论'BlahVM'是什么类型,如果有一个隐含的'DataTemplate',你会在UI中得到它。 'BlahVM'可以声明为对象,其父可以整天切换到不同的子虚拟机。 –