Hunt
Hunt

Reputation: 8435

dynamically create view model with parameter without using autofac

In order to create navigation service in Xamarin using MVVM, in following code GetPage function, I am trying to create page object dynamically in Xamarin after that I am creating model view of that page and assigning a newly created model view to page's binding context.

private static Page GetPage(Type viewModelType)
{

    try
    {
        var pageType = viewModelType.Name.Replace("ViewModel", "Page");
        Page page = (Page)Activator.CreateInstance(Type.GetType($"SEMA.View.{pageType}"));
        page.BindingContext = Activator.CreateInstance(viewModelType);             
        if (page.BindingContext == null)
        {

            Debug.WriteLine("Binding Context is null");

        }

        return page;
    }
    catch (Exception e)
    {
        Debug.WriteLine(e.StackTrace);


    }

    return null;
}

but the issue with this code is I have parameter in my model view see below. MainViewModel(MenuViewModel menuViewModel) hence app is throwing error

Default constructor not found for type SEMA.ViewModel.MainViewModel

If I write default constructor then my parameter constructor i.e. MainViewModel(MenuViewModel menuViewModel) won't get called.

public class MainViewModel : ViewModelBase
{
    private MenuViewModel _menuViewModel;


    public MainViewModel(MenuViewModel menuViewModel)
    {
        _menuViewModel = menuViewModel;
    }

    public MenuViewModel MenuViewModel
    {
        get
        {
            return _menuViewModel;
        }

        set
        {
            _menuViewModel = value;
            OnPropertyChanged();
        }
    }


}

xaml file of main page

<?xml version="1.0" encoding="UTF-8"?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms" 
                  xmlns:SEMA="clr-namespace:SEMA;assembly=SEMA" 
                  xmlns:pages="clr-namespace:SEMA.View" 
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
                  x:Class="SEMA.View.MainPage" >
    <MasterDetailPage.Master>
        <pages:MenuPage BindingContext="{Binding MenuViewModel}" />
    </MasterDetailPage.Master>
    <MasterDetailPage.Detail>
        <ContentPage BackgroundColor="Transparent" />
    </MasterDetailPage.Detail>
</MasterDetailPage>

I am trying to create app based on the xamarin sample provided by xamarin community where in they have used autofac and they are using following code to create page and map it with view model, but I dont want to use autofac hence I am creating view model using Activator page.BindingContext = Activator.CreateInstance(viewModelType); and not using ViewModelBase viewModel = Locator.Instance.Resolve(viewModelType) as ViewModelBase; page.BindingContext = viewModel;

protected Page CreateAndBindPage(Type viewModelType, object parameter)
{
    Type pageType = GetPageTypeForViewModel(viewModelType);

    if (pageType == null)
    {
        throw new Exception($"Mapping type for {viewModelType} is not a page");
    }

    Page page = Activator.CreateInstance(pageType) as Page;
    ViewModelBase viewModel = Locator.Instance.Resolve(viewModelType) as ViewModelBase;
    page.BindingContext = viewModel;

    return page;
}

Upvotes: 1

Views: 817

Answers (1)

Roger Leblanc
Roger Leblanc

Reputation: 1583

Activator.CreateInstance has an overload that accepts an array of objects as parameters for the constructor.

private static Page GetPage(Type viewModelType, MenuViewModel menuViewModel)
{
    //...
    page.BindingContext = Activator.CreateInstance(viewModelType, new object[] { menuViewModel });
    //...
}

Upvotes: 1

Related Questions