3

I am building a simple master-details GUI using WPF/MVVM/Prism for some data coming from a Restful service.

I have the main window as my main view with a corresponding view model.

I have a user control to show the master data and it's got its own view model as well.

I have added an instance of the master data view model into the main view model. I am not sure if this is the best practice. Then I've set the data context of the main view in the code behind, and of the user control using the XAML of the main view.

<Window x:Class="MyNamespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyNamespace"
        xmlns:views="clr-namespace:MyNamespace.Views"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">

    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding LoginAndLoadMasterDataCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <views:MasterDataView DataContext="{Binding MasterData, Mode=OneWay}" />
    </Grid>
</Window>

Now I got two commands one to login to the restful and this is in the main view model, and another to load the master data and this is in the child view model. Loading data might take few seconds.

I want to fire the two commands in sequence, and I've tried Prism composite command and also tried to add both commands to be triggered on view load but both way don't enable me to control the sequence of commands so loading data is attempted before login returns which causes an exception to be thrown.

internal class MainViewModel : BindableBase
{
    private readonly ApiClient client = new ApiClient();

    public MasterDataViewModel MasterData { get; }

    public ICommand LoginAndLoadMasterDataCommand { get; }

    public  MainViewModel()
    {
        MasterData = new MasterDataViewModel(client);

        CompositeCommand loginCommand = new CompositeCommand(false);
        loginCommand.RegisterCommand(new DelegateCommand(async () => await client.Login()));
        loginCommand.RegisterCommand(MasterData.LoadDataCommand);

        LoginCommand = loginCommand;
    }
}

Notice that the login method and the load data method are both async methods.

What is a good practice to handle such a situation?

And also what if I wanted to set the window to a certain state (e.g. greyed out or showing a 'wait' modal) until the loading finishes?

1

I would create one single DelegateCommand to call Login and LoadData in such manner that I have control over the order they are called:

LoginAndLoadMasterDataCommand = new DelegateCommand(
    async () =>
    {
        IsLoading = true;

        bool loginSuccesful = await client.Login();
        if (loginSuccesful)
            await MasterData.LoadData();

        IsLoading = false;
    }

IsLoading is an observable property that you can bind to some ProgressBar or other control's Visibility to provide feedback to the user that the application is working. And MasterData.LoadData is, supposedly, the awaitable method that your MasterData.LoadDataCommand is calling.

  • +1; I'd do the same thing, use only 1 command triggered by MainView. To add to the answer: I have added an instance of the master data view model into the main view model. I am not sure if this is the best practice. - I guess its OK, because your MainView contains a MasterDataView, therefore you MainViewModel should contain a MasterDataViewModel too. – Emerson Cardoso Nov 30 '17 at 13:02

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.