问题
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