Home > database >  WPF - Prism - how to pass parameters to Drawer's ViewModel
WPF - Prism - how to pass parameters to Drawer's ViewModel

Time:09-13

This is a sample .xaml code that I have, I'm using DrawerHost Control from MaterialDesignInXamlToolkit

<UserControl 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    d:DataContext="{d:DesignInstance viewModels:UserControlViewModel}"
    mc:Ignorable="d"
    xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes">
    
    <materialDesign:DrawerHost IsRightDrawerOpen="{Binding IsDrawerOpen}" OpenMode="Default">
        <materialDesign:DrawerHost.RightDrawerContent>
            <views:RightDrawerView />
        </materialDesign:DrawerHost.RightDrawerContent>
            <!-- Main Content -->
    </materialDesign:DrawerHost>
</UserControl>

RightDrawerViewModel will be set to be the DataContext of RightDrawerView via Prism's ViewModelLocationProvider.

My Question: When setting IsDrawerOpen to true, how can UserControlViewModel pass parameters to RightDrawerViewModel? as RightDrawerViewModel is not called via Prism's methods (regionManager?.RequestNavigate, dialogService?.ShowDialog).

CodePudding user response:

If you want to pass parameters, you can either RequestNavigate instead of setting IsDrawerOpen (which needs a region and an custom RegionAdapter for the DrawerHost) or you create a service known to both the view model that wants to open the drawer and the drawer's view model and put all data there before setting IsDrawerOpen.

A third option is to create a new DrawerViewModel when you want to open the drawer and assign it to a property on the parent view model and bind it to the drawer's content's data context. Also, remove IsDrawerOpen and replace it either with a style or a converter that observe the view model-property on the parent.

I'd go for the first option only if I were forced to go view first, otherwise always prefer the third one. The second's ugly and presented for completeness only.

CodePudding user response:

My Solution..

  1. First, Define NavigationParameters property in RightDrawerViewModel
public class RightDrawerViewModel {
    public NavigationParameters NavigationParameters { set; get; }
}

In my case, I have predefined BaseViewModel that implements INavigationAware, so I've added NavigationParameters property to it (this way I can hold the parameters that are passed via RequestNavigate even for other ViewModels that inherit from BaseViewModel and use this property for the rest of the OnNavigatedTo code)

public class RightDrawerViewModel : BaseViewModel {
    // ..
}

public abstract class BaseViewModel : INavigationAware {
        
    public NavigationParameters NavigationParameters { set; get; } // parameters holder
    
    public void OnNavigatedTo(NavigationContext navigationContext)
    {
        if (navigationContext?.Parameters != null)
            NavigationParameters = navigationContext.Parameters;
        // ..
    }

    public void OnNavigatedFrom(NavigationContext navigationContext)
    {
        NavigationParameters = null;
    }

    public bool IsNavigationTarget(NavigationContext navigationContext)
    {
        return true;
    }
    
    // ..
}
  1. Then, Pass the parameters before setting IsDrawerOpen to true..
// 1. Let UserControl class implement an interface that has `DataContext GetRightDrawerDataContext();` method, 
// 2. Inject services instnace in ctor of UserControlViewModel via Prism's Ioc Container
if (services.GetRightDrawerDataContext() is INavigationAware nv)
    nv.NavigationParameters = parameters; // parameters to pass

IsDrawerOpen = true;
  1. Finally, RightDrawerViewModel can get the parameters from NavigationParameters property.
var b = NavigationParameters?.TryGetValue("Parameter1Key", out object object1Instance);
  • Related