Hello Xamarin Gurus,
I am doing a little experiment with inheritance and generics, here is the idea:
(I have a diagram to represent things more clearly, but I'm not authorised to post links yet)
The Models:
public interface IEntity { }
public abstract class Entity : IEntity
{
public int Id { get; set; }
}
public class Instance : Entity
{
public string Name { get; set; }
}
public class Volume : Entity
{
public float VolumeValue { get; set; }
}
The ViewModels:
public interface IEntityViewModel<T> where T : IEntity { }
public abstract class EntityViewModel<T> : IEntityViewModel<T> where T : Entity
{
public T Model { get; set; }
}
public class InstanceViewModel : EntityViewModel<Instance> { }
public class VolumeViewModel : EntityViewModel<Volume> { }
Now for the Views... this is where it gets complicated and broken.
EntityPage.xaml.cs:
public partial class EntityPage<T> : ContentPage where T : Entity
{
public EntityPage(EntityViewModel<T> model)
{
InitializeComponent(); // error : method do not exist
BindingContext = model;
}
}
EntityPage.xaml:
<ContentPage x:Class="XamarinSample.View.EntityPage">
<ContentPage.Content>
<StackLayout >
<Label Text="The Id is:"/>
<Label Text="{Binding Model.Id}"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
VolumePage.xaml.cs:
public partial class VolumePage : EntityPage<Volume>
{
public VolumePage(VolumeViewModel model) : base(model)
{
InitializeComponent();
}
}
VolumePage.xaml:
<view:EntityPage x:TypeArguments="model:Volume" <!-- I specify the type of the generic type that EntityPage uses -->
xmlns:view="clr-namespace:XamarinSample.View"
xmlns:model="clr-namespace:XamarinSample.Model"
x:Class="XamarinSample.View.VolumePage">
<ContentPage.Content>
<StackLayout >
<Label Text="The VolumeValue is:"/>
<Label Text="{Binding Model.VolumeValue}"/>
</StackLayout>
</ContentPage.Content>
</view:EntityPage>
The issue here is that I cannot call InitializeComponent()
in the constructor of EntityPage because the generated code doesn't copy the genericity.
Generated code:
public partial class EntityPage : global::Xamarin.Forms.ContentPage {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
private void InitializeComponent() {
global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(EntityPage));
}
}
If I comment the problematic line and compile I get the following result from this quick&dirty initialisation:
MainPage = new VolumePage(new ViewModel.VolumeViewModel()
{
Model = new Model.Volume() { Id = 50, VolumeValue = 500 }
});
(still can't post links )
The info about VolumeValue
is displayed but not the info about the Id
Is there any way to make this work ? From the research I did prior to posting this, I would say it's not possible.
From your experience with Xamarin.Forms, would you say that it is better to use Composition over Inheritance to represent objects somewhat similar ? I am highly tempted to say yes.
Thanks in avance !