Reputation: 24572
Here's an example of what I need to do now. Sometimes I have one span, sometimes more.
Note that this post is similar to that of another question. For the other question I had only one comment to use a custom control with no more advice offered and one answer to use JavaScript. I tried to add a second bounty to that question but it gave me the option of only adding a bounty of 500 points. The question is now so old that I doubt anyone will see it any more and as I cannot add a bounty (unless it's 500 points) I cannot give it more visibility.
Here's what I would like to simplify:
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Hello " />
<Span Text="Hello " />
<Span Text=" Some more text." />
</FormattedString>
</Label.FormattedText>
</Label>
Here's what I would like to do instead of typing in <Label><Label.FormattedText><FormattedString>
I would like to get some way to do this with only entering in <template:FormattedLabel>
<template:FormattedLabel>
<Span Text="Hello " />
<Span Text="Hello " />
<Span Text=" Some more text." />
</template:FormattedLabel>
or
<template:FormattedLabel>
<Span Text="Hello " />
</template:FormattedLabel>
Note that I have looked into custom controls but as far as I see I cannot find a way to make these accept some inside content which in this case would be one or more spans.
I have an example of something similar which could perhaps be used but I am not sure how to apply it. What I was hoping for was a template like this in the XAML below which is does something similar to what I need but for content pages:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Japanese;assembly=J"
xmlns:t="clr-namespace:J.Templates"
x:Class="Japanese.Templates.ContentScrollable"
x:Name="ContentPage" >
<ContentPage.Content>
<t:Stack Orientation="Vertical">
<ScrollView x:Name="scroll">
<ContentView Content="{Binding Source={x:Reference ContentPage}, Path=InnerContent}"
Margin="{DynamicResource PageMargin}" />
</ScrollView>
</t:Stack>
</ContentPage.Content>
</ContentPage>
With its C# back end:
public partial class ContentScrollable : ContentPage
{
public static readonly BindableProperty InnerContentProperty = BindableProperty.Create(nameof(InnerContent), typeof(View), typeof(ContentScrollable));
public View InnerContent
{
get => (View)this.GetValue(InnerContentProperty);
set => this.SetValue(InnerContentProperty, value);
}
public ContentScrollable()
{
InitializeComponent();
}
}
How can I accomplish what I am looking for?
Upvotes: 4
Views: 210
Reputation: 2119
You can do the following:
<!-- FormattedLabel.xaml -->
<?xml version="1.0" encoding="UTF-8"?>
<Label
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="YourNamespaceForTemplates.FormattedLabel" />
// FormattedLabel.xaml.cs
[ContentProperty(nameof(Spans))]
public partial class FormattedLabel : Label
{
private readonly ObservableCollection<Span> _spans;
public IList<Span> Spans => _spans;
public FormattedLabel()
{
_spans = new ObservableCollection<Span>();
_spans.CollectionChanged += OnSpansChanged;
InitializeComponent();
}
private void OnSpansChanged(object sender, NotifyCollectionChangedEventArgs e)
{
FormattedText?.Spans?.Clear();
FormattedText = FormattedText ?? new FormattedString();
Spans.ForEach(FormattedText.Spans.Add);
}
}
Basically, in this extension of Label
we define the content to be a list of Span
items, which will allow you to define them in XAML inside <FormattedLabel></FormattedLabel>
. To make it work, we pass these items down to this.FormattedText.Spans
.
To use it:
<template:FormattedLabel>
<Span Text="Hello " />
<Span Text="Hello " />
<Span Text=" Some more text." />
</template:FormattedLabel>
I have just checked it and it works perfectly. I hope this helps!
Upvotes: 4