-1

I have XAML code that I use to set up a frame and frame heading like this:

<Label Text="ABC" />
<t:ContentFrame>
   <Label Text="ABC" />
</t:ContentFrame>

For ContentFrame I use a C# template here:

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

    public ContentFrame()
    {
        Content = contentStack;
        HasShadow = false;
        SetDynamicResource(BackgroundColorProperty, "ContentFrameBackgroundColor");
        SetDynamicResource(BorderColorProperty, "ContentFrameBorderColor");
        SetDynamicResource(CornerRadiusProperty, "ContentFrameCornerRadius");
    }
}

Is there a way that I could combine the setting of the heading into the ContentFrame class so the same thing could be achieved with:

<t:ContentFrame Heading="ABC">
   <Label Text="ABC" />
</t:ContentFrame>
Cfun
  • 8,442
  • 4
  • 30
  • 62
Alan2
  • 23,493
  • 79
  • 256
  • 450

1 Answers1

-1

You need a Bindable property for this:

public class ContentFrame : CustomFrame
{
StackLayout contentStack { get; } = new StackLayout()
    {
        Spacing = 0,
        Padding = new Thickness(0),
        Orientation = StackOrientation.Vertical
    };
    public IList<View> Contents { get => contentStack.Children; }
    public static readonly BindableProperty HeadingProperty =
            BindableProperty.Create(nameof(Heading), typeof(string),
            typeof(ContentFrame), null, propertyChanged: OnHeadingChanged);

    public string Heading
    {
        get => (Heading)GetValue(HeadingProperty);
        set => SetValue(HeadingProperty, value);
    }

static void OnHeadingChanged(BindableObject bindable, object oldValue, object newValue) {
//whatever you want to handle
 }

    public ContentFrame()
    {
        Content = contentStack;
        HasShadow = false;
        SetDynamicResource(BackgroundColorProperty, "ContentFrameBackgroundColor");
        SetDynamicResource(BorderColorProperty, "ContentFrameBorderColor");
        SetDynamicResource(CornerRadiusProperty, "ContentFrameCornerRadius");
    }
}

If you don't require InotifypropertyChanged you can remove OnHeadingChanged (also from inside BindableProperty.Create(), if require you can add the below declaration.

Cfun
  • 8,442
  • 4
  • 30
  • 62
  • Can you give an example of this inside of the C# code of the question so I can see the complete picture of how to do this. Thanks – Alan2 Dec 05 '20 at 12:27
  • I was meaning the full code for public class ContentFrame. I think it's good to make it clear so others could see how to add what's needed. – Alan2 Dec 05 '20 at 14:50
  • I think it was probably downvoted as you just gave a snippet of code and used ... rather than add in what was actually needed. If you want to add in the complete code I'm happy to accept the answer. Thanks – Alan2 Dec 06 '20 at 05:43
  • Thanks, but your answer does not show how to use Heading. You have just added a binding. What I need to do is to be able to take the value of the Heading and add that in as the first child of the Stack followed by the contentStack.Children. That's the hard part of the question for me. I want to eliminate the need to have a Label above the content frame and move that label into the content frame itself. – Alan2 Dec 06 '20 at 14:55
  • 1
    I am sorry but your initial question didn't clarify that point, I'll try. – Cfun Dec 06 '20 at 14:58
  • I accepted your answer so you can be awarded the points and I will create another question that's a bit more specific. – Alan2 Dec 07 '20 at 06:52
  • 1
    I have added this new question https://stackoverflow.com/questions/65178643/how-can-i-add-an-element-to-a-template-before-a-list-of-elements – Alan2 Dec 07 '20 at 08:57