Here's the C# template code I have:
public class PopupFrame : Frame
{
public PopupFrame()
{
this.SetDynamicResource(BackgroundColorProperty, "PopUpBackgroundColor");
this.SetDynamicResource(CornerRadiusProperty, "PopupCornerRadius");
HasShadow = true;
HorizontalOptions = LayoutOptions.FillAndExpand;
Padding = 0;
VerticalOptions = LayoutOptions.Center;
}
}
I am using it like this:
<t:PopupFrame>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<t:PopupHeader Text="Copy Deck" />
<t:PopupEntryHeader Text="New Deck Name" />
More XAML here
</StackLayout>
</t:PopupFrame>
Is there some way that I can code PopupFrame
so that the StackLayout
is part of it and it takes content.
Here's what I would like to code:
<t:PopupFrame>
<t:PopupHeader Text="Copy Deck" />
<t:PopupEntryHeader Text="New Deck Name" />
More XAML here
</t:PopupFrame>
The Xamarin. Forms ContentView class is a type of Layout that contains a single child element and is typically used to create custom, reusable controls. The ContentView class inherits from TemplatedView .
Gets or sets a value which determines if the Layout should clip its children to its bounds.
The StartAndExpand , CenterAndExpand , EndAndExpand , and FillAndExpand values are used to define the alignment preference, and whether the view will occupy more space if available within the parent StackLayout . The default value of a view's HorizontalOptions and VerticalOptions properties is LayoutOptions. Fill .
The Xamarin. Forms Frame class is a layout used to wrap a view with a border that can be configured with color, shadow, and other options. Frames are commonly used to create borders around controls but can be used to create more complex UI. For more information, see Advanced Frame usage.
PopupFrame.cs
public class PopupFrame : Frame
{
StackLayout PopupContent;
public IList<View> Body
{
get => PopupContent.Children;
}
public PopupFrame()
{
PopupContent = new StackLayout();
SetDynamicResource(Frame.BackgroundColorProperty, "PopUpBackgroundColor");
SetDynamicResource(Frame.CornerRadiusProperty, "PopupCornerRadius");
HasShadow = true;
HorizontalOptions = LayoutOptions.FillAndExpand;
Padding = 0;
VerticalOptions = LayoutOptions.Center;
Content = PopupContent;
}
Now you can use
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage 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">
<StackLayout>
<t:PopupFrame>
<t:PopupFrame.Body>
<t:PopupHeader Text="Test header"/>
<Label Text="Test content"/>
</t:PopupFrame.Body>
</t:PopupFrame>
</StackLayout>
</ContentPage>
If i am right, you could achieve this by setting the ContentProperty
attribute to your PopupFrame
class to a property that is itself a collection. This would override the ContentProperty
of Frame
which is Content
to allow you to set multiple views as the contents instead of just one which is the default for Frame...
So, if all this sounds good to you, keep on reading.
You could define a ContentProperty
for your PopupFrame
class, like this:
[Xamarin.Forms.ContentProperty("Contents")]
class PopupFrame : Frame
{
StackLayout contentStack { get; } = new StackLayout();
public IList<View> Contents { get => contentStack.Children; }
public PopupFrame()
{
Content = contentStack;
HasShadow = true;
HorizontalOptions = LayoutOptions.FillAndExpand;
Padding = 0;
VerticalOptions = LayoutOptions.Center;
}
}
Then your are able to do something like what you want:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage 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">
<StackLayout>
<t:PopupFrame>
<t:PopupHeader Text="Test header"/>
<Label Text="Test content"/>
</t:PopupFrame>
</StackLayout>
</ContentPage>
Which on my side works showing both the PopupHeader
and the Label
:
What follows is taken literally from the book of Ch. Petzold on Xamarin.Forms.
Every class used in XAML is allowed to define one property as a content property (sometimes also called the class’s default property). For this content property, the property-element tags are not required, and any XML content within the start and end tags is automatically assigned to this property. Very conveniently, the content property of ContentPage
is Content
, the content property of StackLayout
is Children
, and the content property of Frame
is Content
.
These content properties are documented, but you need to know where to look. A class specifies its content property by using the ContentPropertyAttribute. If this attribute is attached to a class, it appears in the online Xamarin.Forms API documentation along with the class declaration. Here’s how it appears in the documentation for ContentPage
:
[Xamarin.Forms.ContentProperty("Content")]
public class ContentPage : TemplatedPage
If you say it aloud, it sounds a bit redundant: "The Content property is the content property of ContentPage."
The declaration for the Frame
class is similar:
[Xamarin.Forms.ContentProperty("Content")]
public class Frame : ContentView
StackLayout
doesn’t have a ContentProperty
attribute applied, but StackLayout
derives from Layout<View>
, and Layout<T>
has a ContentProperty
attribute:
[Xamarin.Forms.ContentProperty("Children")]
public abstract class Layout<T> : Layout, IViewContainer<T>
where T : View
The ContentProperty
attribute is inherited by the classes that derive from Layout<T>
, so Children
is the content property of StackLayout
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With