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?

Brandon Minnick
  • 13,342
  • 15
  • 65
  • 123
Viktor Szekeress
  • 175
  • 1
  • 13
  • Looks fine to me. Perhaps it's because your class is marked as `abstract`? You can't instantiate an abstract class, try removing it. – Mike Eason Nov 16 '15 at 09:56
  • Of course I have derived classes which I'm trying to instantiate. Have you tried to run the code from question? – Viktor Szekeress Nov 17 '15 at 16:18
  • @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 you – thorkia Mar 28 '16 at 11:33
  • Unfortunately no. I used different approach with interface. But that didn't solve the code duplicity. – Viktor Szekeress Mar 30 '16 at 11:51

3 Answers3

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>
Brandon Minnick
  • 13,342
  • 15
  • 65
  • 123
Adam Hockemeyer
  • 111
  • 1
  • 3
1

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">
Daspuru
  • 287
  • 4
  • 6
0

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

    public BasePage()
    {
        BindingContext = new TBaseVM();
    }
Saket Sinha
  • 81
  • 1
  • 5