Page with type parameter
Asked Answered
B

3

8

I would like to use new feature of UWP -> x:Bind. In order to that, all my pages need to have ViewModel property (as described in tutorials). To avoid code duplicity, I have established base class as follows:

public abstract class BasePage<TBaseVM> : Page, where TBaseVM : BaseVM
{
    public TBaseVM VM { get; private set; }

    protected BasePage()
    {
        DataContextChanged += (s, e) => VM = e.NewValue as TBaseVM;            
    }
}

As you can see this BasePage class contains property called "VM" and property is of type BaseVM. Hence, I don't need to define VM property on each derived class.

Then I created derived page 'MainPage' defined in xaml as follows:

<pages:BasePage
x:Class="Realarm.View.Pages.MainPage"
x:TypeArguments="viewModel:MainVM">

By doing that, even Resharper's Intellisense offers me properties from "MainVM" in MainPage.xaml, thus is can write:

<ListView ItemsSource="{x:Bind VM.AlarmsVM}">

Unfortunately, when I try to build the project, I get error in MainPage.g.i.cs:

Severity Code Description Project File Line Error CS0305 Using the generic type 'BasePage' requires 1 type arguments Realarm D:...\Realarm\obj\x86\Debug\View\Pages\MainPage.g.i.cs 13

Any help?

Bracelet answered 14/11, 2015 at 12:50 Comment(4)
Looks fine to me. Perhaps it's because your class is marked as abstract? You can't instantiate an abstract class, try removing it.Storekeeper
Of course I have derived classes which I'm trying to instantiate. Have you tried to run the code from question?Bracelet
@de_ViL Did you solve this? I am having the same issue and everything I find says it should work, but I get the same error as youSarsenet
Unfortunately no. I used different approach with interface. But that didn't solve the code duplicity.Bracelet
P
4

I got this working using Xamarin.Forms.

Base Page:

public abstract class BaseContentPage<TViewModel> : ContentPage where TViewModel : BaseViewModel, new()

HomePage.cs:

public partial class HomePage : BaseContentPage<HomeViewModel>

HomePage.xaml:

<d:BaseContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:d="clr-namespace:Sample.Pages;assembly=Sample" 
    xmlns:vm="clr-namespace:Sample.ViewModels;assembly=Sample" 
    x:Class="Sample.Pages.HomePage" 
    x:TypeArguments="vm:HomeViewModel">
    <ContentPage.Content>
    </ContentPage.Content>
</d:BaseContentPage>
Piapiacenza answered 14/1, 2018 at 17:11 Comment(0)
S
2

Just add a x:TypeArguments definition at the top of the XAML:

<v:BasePage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:v="clr-namespace:YourApp.Views"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            xmlns:d="http://xamarin.com/schemas/2014/forms/design"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:vm="clr-namespace:YourApp.ViewModels"
            mc:Ignorable="d"
            x:TypeArguments="vm:HomeViewModel"
            x:Class="YourApp.MainPage">
Spelldown answered 11/6, 2020 at 18:33 Comment(0)
H
0

Worked for me as well when I set the BindingContext as given below in Base Page's constructor:

    public BasePage()
    {
        BindingContext = new TBaseVM();
    }
Hector answered 6/12, 2019 at 6:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.