簡體   English   中英

我如何在視圖/視圖模型所提供的對象之間進行切換,這些對象是提前進行異步初始化的?

[英]How can I switch around Views/ViewModels that are provided objects which are asychronously initialized ahead of time?

當VM(因此需要Views)需要接受其對象被異步初始化的構造函數參數時,如何在Views / ViewModels之間切換。 或者,是否有更好的方法為視圖/ VM提供這些對象?

當View / VM不使用構造函數參數時,這是我以前的實現。

MainWindow.xaml

當ContentControl更改時,使用DataTemplates在視圖之間切換。

<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

創建新的ViewModel,然后將CurrentViewModel設置為相關的ViewModel。 更改后,DataTemplate將根據上述DataTemplates切換視圖。

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 (這是我切入和切出的VM之一):

通過以下方式在其xaml中先前定義的DataContext:

<UserControl.DataContext>
    <viewModels:GameListingViewModel />
</UserControl.DataContext>-->

以上所有工作均符合預期。


現在,由於具有新功能,這些ViewModel需要接收1個或多個對象才能起作用,因此我想將它們傳遞給構造函數。 結果,我不再可以在xaml中定義DataContext,但是可以使用背后的代碼來創建它們。

public GameListingView(ConfigSettings configSettings, GameBoxHelper gameBoxHelper)
{
    InitializeComponent();
    DataContext = new GameListingViewModel(configSettings, gameBoxHelper);
}

問題在於,這要求View的構造函數也要接收相關的對象(否則我將從何處獲取這些對象?),這使得DataTemplate回到MainWindow.xaml不再起作用。

Xaml錯誤消息: “類型'GameListingView'不能用作對象元素,因為它不是公共的或未定義公共的無參數構造函數或類型轉換器。找不到默認的構造函數。”

重要的是,傳遞給這些ViewModels的對象還沒有立即准備好。 MainWindowViewModel會事先對其進行初始化,這是異步進行的。 根據以上錯誤消息,我認為可以使用TypeConverter (將要傳遞的對象綁定到參數,並在xaml中將它們分配為TypeConverter的參數),但是我看不到它將如何工作,因為它們不是立即准備好(異步初始化)。

供參考:目的是在加載應用程序時,所有初始化都預先完成(從文件系統中讀取配置設置,從Web API中檢索一些數據,等等),以便在需要時可以立即進行其余操作。應用程序響應速度更快。 我寧願不要將對象的異步初始化移動到使用它們的VM。

我不使用任何MVVM框架。

考慮到所有這些,我的問題是如何繼續為我的視圖/虛擬機切換,同時為它們提供提前異步初始化的對象?


當應用程序啟動時,您不能在App.xaml.cs或bootstrapper類中創建依賴項,然后將它們作為構造函數參數傳遞給MainViewModel嗎?

從App.xaml中的“ Application根元素中刪除StartupUri屬性,並覆蓋App.xaml.cs中的OnStartup方法:

public partial class App : Application
{
    protected async override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var yourDependency = await YourClass.CreateAsync();

        MainWindowViewModel vm = new MainWindowViewModel(yourDependency);
        MainWindow mainWindow = new WpfApplication4.MainWindow() { DataContext = vm };
        mainWindow.Show();
    }
}

然后, MainViewModel類將負責注入它創建的其他視圖模型,以及由App類注入的依賴項。

或者,如果您希望在MainViewModel類內部初始化依賴項,則可以在App類中初始化該依賴項,即MainViewModel

請參閱Stephen Cleary的博客文章,以獲取有關異步工廠方法和異步構造的更多信息: http : //blog.stephencleary.com/2013/01/async-oop-2-constructors.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM