How can I add an element to a template before a list of elements?

妖精的绣舞 提交于 2020-12-15 06:48:22

问题


I have created a frame with a StackLayout inside of it. What I would like to do is before the items are added to the inside of the frame then I would like Heading label to appear. Here is what I have so far:

public class ContentFrame : Frame
{
    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);
    }

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

What I would like is to be able to use it like this:

 <t:ContentFrame Heading="The heading here">
    <Label Text="ABC" />
    <Label Text="ABC" />
    <Label Text="GHI" />
 </t:ContentFrame>

and have the output look like this:

 ********************
 * The heading here *
 * ABC              *
 * DEF              *
 * GHI              *
 ********************

Does anyone know how I can modify ContentFrame so that the heading is added as an element before the containing elements?

Here's the current code I am trying based on Shubham's suggestion:

[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()
    {
        var heading = new Label();
        if (!string.IsNullOrEmpty(Heading))
        {

            heading.Text = Heading;
            contentStack.Children.Insert(0, heading);
        }
        Content = contentStack;
        HasShadow = false;
        SetDynamicResource(BackgroundColorProperty, "ContentFrameBackgroundColor");
        SetDynamicResource(BorderColorProperty, "ContentFrameBorderColor");
        SetDynamicResource(CornerRadiusProperty, "ContentFrameCornerRadius");
        SetDynamicResource(ElevationProperty, "ContentFrameElevation");
        SetDynamicResource(MarginProperty, "ContentFrameMargin");
        SetDynamicResource(PaddingProperty, "ContentFrameBorderPadding");
    }

    public static readonly BindableProperty HeadingProperty =
        BindableProperty.Create(nameof(Heading), typeof(string), typeof(ContentFrame), null);


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

回答1:


According to your description and code, you want to create custom frame with bindableproperty, I modify your code, please take a following code. Don't forget implement bindableproperty propertyChanged method.

public class ContentFrame : Frame
{
    StackLayout contentStack { get; } = new StackLayout()
    {
        Spacing = 0,
        Padding = new Thickness(0),
        Orientation = StackOrientation.Vertical
    };

    Label headinglabel { get; set; } = new Label()
    {
        TextColor=Color.Red
    };
    public IList<View> Contents { get => contentStack.Children; }
    public static readonly BindableProperty HeadingProperty =
            BindableProperty.Create(nameof(Heading), typeof(string),
            typeof(ContentFrame), null, propertyChanged: OnHeadingChanged);

    private static void OnHeadingChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var customframe = (ContentFrame)bindable;
        customframe.headinglabel.Text = newValue.ToString();
    }

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

    public ContentFrame()
    {
        contentStack.Children.Add(headinglabel);
      
        Content = contentStack;
        HasShadow = false;
       
    }
}

<ContentPage
x:Class="demo3.customcontrol.Page4"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:demo3.customcontrol">
<ContentPage.Content>
    <StackLayout>
        <control:ContentFrame Heading="The heading here">
            <control:ContentFrame.Contents>
                <Label Text="ABC" />
                <Label Text="ABC" />
                <Label Text="GHI" />
            </control:ContentFrame.Contents>

        </control:ContentFrame>
    </StackLayout>
</ContentPage.Content>

The screenshot:




回答2:


Something like this

public class ContentFrame : Frame
{
    Label headingLabel { get; } = new Label()
    {
        FontSize = 18,
        Text = "default",//or string.Empty or null
        //Style = Use some header style
        TextColor = Color.Green
    };
    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);
    }

    public ContentFrame()
    {
        if (!string.IsNullOrEmpty(Heading))
        {
            headingLabel.Text = Heading;
            contentStack.Children.Insert(0, headingLabel);
        }
        Content = contentStack;
        HasShadow = false;
        SetDynamicResource(BackgroundColorProperty, "ContentFrameBackgroundColor");
        SetDynamicResource(BorderColorProperty, "ContentFrameBorderColor");
        SetDynamicResource(CornerRadiusProperty, "ContentFrameCornerRadius");
    }
}


来源:https://stackoverflow.com/questions/65178643/how-can-i-add-an-element-to-a-template-before-a-list-of-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!