I have created a Card control and handlers for it (CardHandler, CardHandler.Android and CardHandler.iOS). PlatformView in Android handler is Google.Android.Material.Card.MaterialCardView. In iOS handler PlatformView is UIView.
But something is wrong because I get next error in shared handler: Partial declarations of 'CardHandler' must not specify different base classes
In CardHandler.iOS I have next:
Full code:
public enum CardType
{
Elevated, Filled, Outlined
}
public interface ICard : IView, IPadding, IPaddingElement
{
View Content { get; set; }
CardType Type { get; set; }
}
[ContentProperty(nameof(Content))]
public class Card : View, ICard
{
public event EventHandler Clicked;
public event EventHandler LongClicked;
public static readonly BindableProperty PaddingProperty = PaddingElement.PaddingProperty;
public static readonly BindableProperty ContentProperty =
BindableProperty.Create(nameof(Content), typeof(View), typeof(Card), default(View), propertyChanged: OnContentChanged);
public static readonly BindableProperty TypeProperty =
BindableProperty.Create(nameof(CardType), typeof(CardType), typeof(ICard), CardType.Elevated);
public static readonly BindableProperty ClickedCommandProperty =
BindableProperty.Create(nameof(ClickedCommand), typeof(ICommand), typeof(ICard), default(ICommand));
public static readonly BindableProperty LongClickedCommandProperty =
BindableProperty.Create(nameof(LongClickedCommand), typeof(ICommand), typeof(ICard), default(ICommand));
public static readonly BindableProperty ClickedCommandParameterProperty =
BindableProperty.Create(nameof(ClickedCommandParameter), typeof(object), typeof(ICard), default);
public static readonly BindableProperty LongClickedCommandParameterProperty =
BindableProperty.Create(nameof(LongClickedCommandParameter), typeof(object), typeof(ICard), default);
public object ClickedCommandParameter
{
get => GetValue(ClickedCommandParameterProperty);
set => SetValue(ClickedCommandParameterProperty, value);
}
public object LongClickedCommandParameter
{
get => GetValue(LongClickedCommandParameterProperty);
set => SetValue(LongClickedCommandParameterProperty, value);
}
public ICommand ClickedCommand
{
get => (ICommand)GetValue(ClickedCommandProperty);
set => SetValue(ClickedCommandProperty, value);
}
public ICommand LongClickedCommand
{
get => (ICommand)GetValue(ClickedCommandProperty);
set => SetValue(ClickedCommandProperty, value);
}
public Thickness Padding
{
get => (Thickness)GetValue(PaddingElement.PaddingProperty);
set => SetValue(PaddingElement.PaddingProperty, value);
}
public CardType Type
{
get => (CardType)GetValue(TypeProperty);
set => SetValue(TypeProperty, value);
}
public View Content
{
get => (View)GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
Thickness IPaddingElement.PaddingDefaultValueCreator() => new Thickness(double.NaN);
static void OnContentChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is Card card)
card.OnBindingContextChanged();
}
void IPaddingElement.OnPaddingPropertyChanged(Thickness oldValue, Thickness newValue)
{
}
public void SendClicked()
{
Clicked?.Invoke(this, EventArgs.Empty);
if (ClickedCommand != null && ClickedCommand.CanExecute(ClickedCommandParameter))
ClickedCommand.Execute(ClickedCommandParameter);
}
public void SendLongClicked()
{
LongClicked?.Invoke(this, EventArgs.Empty);
if (LongClickedCommand != null && LongClickedCommand.CanExecute(LongClickedCommandParameter))
LongClickedCommand.Execute(LongClickedCommandParameter);
}
}
static class PaddingElement
{
public static readonly BindableProperty PaddingProperty =
BindableProperty.Create(nameof(IPaddingElement.Padding), typeof(Thickness), typeof(IPaddingElement), default(Thickness),
propertyChanged: OnPaddingPropertyChanged,
defaultValueCreator: PaddingDefaultValueCreator);
static void OnPaddingPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
((IPaddingElement)bindable).OnPaddingPropertyChanged((Thickness)oldValue, (Thickness)newValue);
}
static object PaddingDefaultValueCreator(BindableObject bindable)
{
return ((IPaddingElement)bindable).PaddingDefaultValueCreator();
}
public static readonly BindableProperty PaddingLeftProperty =
BindableProperty.Create("PaddingLeft", typeof(double), typeof(IPaddingElement), default(double),
propertyChanged: OnPaddingLeftChanged);
static void OnPaddingLeftChanged(BindableObject bindable, object oldValue, object newValue)
{
var padding = (Thickness)bindable.GetValue(PaddingProperty);
padding.Left = (double)newValue;
bindable.SetValue(PaddingProperty, padding);
}
public static readonly BindableProperty PaddingTopProperty =
BindableProperty.Create("PaddingTop", typeof(double), typeof(IPaddingElement), default(double),
propertyChanged: OnPaddingTopChanged);
static void OnPaddingTopChanged(BindableObject bindable, object oldValue, object newValue)
{
var padding = (Thickness)bindable.GetValue(PaddingProperty);
padding.Top = (double)newValue;
bindable.SetValue(PaddingProperty, padding);
}
public static readonly BindableProperty PaddingRightProperty =
BindableProperty.Create("PaddingRight", typeof(double), typeof(IPaddingElement), default(double),
propertyChanged: OnPaddingRightChanged);
static void OnPaddingRightChanged(BindableObject bindable, object oldValue, object newValue)
{
var padding = (Thickness)bindable.GetValue(PaddingProperty);
padding.Right = (double)newValue;
bindable.SetValue(PaddingProperty, padding);
}
public static readonly BindableProperty PaddingBottomProperty =
BindableProperty.Create("PaddingBottom", typeof(double), typeof(IPaddingElement), default(double),
propertyChanged: OnPaddingBottomChanged);
static void OnPaddingBottomChanged(BindableObject bindable, object oldValue, object newValue)
{
var padding = (Thickness)bindable.GetValue(PaddingProperty);
padding.Bottom = (double)newValue;
bindable.SetValue(PaddingProperty, padding);
}
}
Shared handler:
#if IOS || MACCATALYST
using PlatformView = UIKit.UIView;
#elif ANDROID
using PlatformView = Google.Android.Material.Card.MaterialCardView;
#elif NET || (NET6_0 && !IOS && !ANDROID && !TIZEN)
using PlatformView = System.Object;
#endif
public interface ICardHandler : IViewHandler
{
new PlatformView PlatformView { get; }
}
public partial class CardHandler : ICardHandler
{
public static IPropertyMapper<ICard, ICardHandler> Mapper = new PropertyMapper<ICard, ICardHandler>(ViewMapper)
{
[nameof(ICard.Content)] = MapContent,
[nameof(IPadding.Padding)] = MapPadding,
};
public CardHandler(IPropertyMapper mapper, CommandMapper commandMapper = null) : base(mapper, commandMapper)
{
}
public CardHandler() : base(Mapper)
{
}
}
Android handler:
public partial class CardHandler : ViewHandler<ICard, MaterialCardView>
{
private int GetLayoutResource()
{
switch (VirtualView.Type)
{
case CardType.Elevated:
return Resource.Layout.ElevatedCard;
case CardType.Filled:
return Resource.Layout.FilledCard;
case CardType.Outlined:
return Resource.Layout.OutlinedCard;
}
return Resource.Layout.ElevatedCard;
}
protected override MaterialCardView CreatePlatformView()
{
LayoutInflater inflater = LayoutInflater.FromContext(Context);
Android.Views.View view = inflater.Inflate(GetLayoutResource(), null);
MaterialCardView card = (MaterialCardView)view;
card.Clickable = true;
card.Focusable = true;
return card;
}
protected override void ConnectHandler(MaterialCardView platformView)
{
base.ConnectHandler(platformView);
platformView.Click += OnClicked;
platformView.LongClick += OnLongClicked;
}
protected override void DisconnectHandler(MaterialCardView platformView)
{
base.DisconnectHandler(platformView);
platformView.Click -= OnClicked;
platformView.LongClick -= OnLongClicked;
}
private void OnClicked(object sender, EventArgs e)
{
if (VirtualView is Card card)
card.SendClicked();
}
private void OnLongClicked(object sender, Android.Views.View.LongClickEventArgs e)
{
if (VirtualView is Card card)
card.SendLongClicked();
}
public static void MapContent(ICardHandler handler, ICard card)
{
if (card.Content == null)
return;
handler.PlatformView.AddView(card.Content.ToPlatform(handler.MauiContext));
}
public static void MapPadding(ICardHandler handler, IPadding card)
{
Thickness padding = handler.MauiContext.Context.ToPixels(card.Padding);
handler.PlatformView.SetContentPadding((int)padding.Left, (int)padding.Top, (int)padding.Right, (int)padding.Bottom);
}
}
iOS handler:
public partial class CardHandler : ViewHandler<ICard, UIKit.UIView>
{
protected override UIKit.UIView CreatePlatformView()
{
}
}
What is wrong here? Thanks.