Search code examples
c#xamlxamarinxamarin.formscontentproperty

How can I combine XAML and a template into one C# template with Rg.Plugins.Popup?


I would like to simplify the addition of dialog popups in my code to the absolute minimum needed.

Currently I have this code:

<pages:PopupPage
    x:Class="Test.Popup"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup">
    <ContentView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
        <t:PopupFrame>
           <Label Text="ABC" />
           <Label Text="ABC" />
        </t:PopupFrame>
    </ContentView>
</pages:PopupPage>
public partial class Popup : Rg.Plugins.Popup.Pages.PopupPage
{
    public Popup()
    {
        InitializeComponent();
    }
}

And I have PopupFrame here:

[Xamarin.Forms.ContentProperty("Contents")]
public class PopupFrame : Frame
{
    StackLayout contentStack { get; } = new StackLayout()
    {
        Spacing = 0,
        Padding = new Thickness(0),
        Orientation = StackOrientation.Vertical
    };
    public IList<View> Contents { get => contentStack.Children; }

    public PopupFrame()
    {
        Content = contentStack;
        HasShadow = true;
        HorizontalOptions = LayoutOptions.FillAndExpand;
        Padding = 0;
        SetDynamicResource(BackgroundColorProperty, "PopUpBackgroundColor");
        SetDynamicResource(CornerRadiusProperty, "PopupCornerRadius");
        VerticalOptions = LayoutOptions.Center;   
    }
}

Can anyone suggest a way that I can combine these two so that only the following would be required:

<t:PopupPage
    x:Class="Test.Popup"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:t="clr-namespace:Test.Templates">
    <Label Text="ABC" />
    <Label Text="ABC" />
</pages:PopupPage>

So what I am looking for is content for this:

[Xamarin.Forms.ContentProperty("Contents")]
public class Popup : Rg.Plugins.Popup.Pages.PopupPage 
{
}

Update: Here's what I have tried based on the suggested answer:

<?xml version="1.0" encoding="UTF-8" ?>
<pages:PopupPage
    x:Class="Memorise.DecksTab.CopyDeckPopup"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup">
    <Label Text="ABC" />
    <Label Text="ABC" />
</pages:PopupPage>

With backing code:

[Xamarin.Forms.ContentProperty("Contents")]
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CopyDeckPopup : Rg.Plugins.Popup.Pages.PopupPage
{

    PopupFrame contentFrame { get; } = new PopupFrame();

    public IList<View> Contents { get => contentFrame.Contents; }

    public CopyDeckPopup(string clickedDeckName, string clickedDeckDescription)
    {
        BindingContext = new CopyDeckPopupViewModel(clickedDeckName, clickedDeckDescription);
        InitializeComponent();
        Content = new ContentView()
        {
            HorizontalOptions = LayoutOptions.FillAndExpand,
            VerticalOptions = LayoutOptions.FillAndExpand,
            Content = contentFrame
        };
    }

}

It's giving me this error BUT the display is correct and I see two ABCs.

enter image description here


Solution

  • From this piece of code:

    <pages:PopupPage
        x:Class="Test.Popup"
        xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup">
        <ContentView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
            <t:PopupFrame>
               <Label Text="ABC" />
               <Label Text="ABC" />
            </t:PopupFrame>
        </ContentView>
    </pages:PopupPage>
    

    it can be seen that the ContentProperty of PopupPage is a single View (which is being occupied by a ContentView in the code above).

    But if you want to be able to write code like

    <t:PopupPage
        x:Class="Test.Popup"
        xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:t="clr-namespace:Test.Templates">
       <Label Text="ABC" />
       <Label Text="ABC" />
    </pages:PopupPage>
    

    then you want PopupPage's ContentProperty to be such that it is capable of taking a list of items (like to two Labels in the code above) and additionally that those items are set to your PopupFrame which should be placed inside a ContentView...

    All you have to do is modify PopupPage (which i am assuming inherits from ContentPage[?]) to accept multiple items as its contents, as follows

    [Xamarin.Forms.ContentProperty("Contents")]
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class PopupPage : ContentPage
    {
    
        PopupFrame contentFrame { get; } = new PopupFrame();
    
        public IList<View> Contents { get => contentFrame.Contents; }
    
        public PopupPage()
        {
            InitializeComponent();
            Content = new ContentView()
            {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
                Content = contentFrame
            };
        }
    }
    

    By doing that, now you will be able to write the kind of code you want

    <?xml version="1.0" encoding="utf-8" ?>
    <t:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:t="clr-namespace:popupframe"
        x:Class="popupframe.MainPage">
        <Label Text="Label1"/>
        <Label Text="Label2"/>
    </t:PopupPage>