Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Page with type parameter

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?

like image 267
Viktor Szekeress Avatar asked Nov 14 '15 12:11

Viktor Szekeress


People also ask

How do you declare a type parameter?

To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound.

What is a type parameter in C#?

The type parameter is a placeholder for a specific type that the client specifies when they create an instance of the generic type. A generic class cannot be used as-is because it is simply a blueprint for that type.

What is type parameters in generics?

The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, ..., and Tn. To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>".

What is the purpose of an interface constraints on a type parameter?

Interface Type Constraint You can constrain the generic type by interface, thereby allowing only classes that implement that interface or classes that inherit from classes that implement the interface as the type parameter.


2 Answers

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>
like image 91
Adam Hockemeyer Avatar answered Jan 03 '23 17:01

Adam Hockemeyer


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">
like image 26
Daspuru Avatar answered Jan 03 '23 17:01

Daspuru