標籤與可繫結的跨度集合
我建立了包含 FormattedText
屬性包裝的自定義標籤:
public class MultiComponentLabel : Label
{
public IList<TextComponent> Components { get; set; }
public MultiComponentLabel()
{
var components = new ObservableCollection<TextComponent>();
components.CollectionChanged += OnComponentsChanged;
Components = components;
}
private void OnComponentsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
BuildText();
}
private void OnComponentPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
BuildText();
}
private void BuildText()
{
var formattedString = new FormattedString();
foreach (var component in Components)
{
formattedString.Spans.Add(new Span { Text = component.Text });
component.PropertyChanged -= OnComponentPropertyChanged;
component.PropertyChanged += OnComponentPropertyChanged;
}
FormattedText = formattedString;
}
}
我新增了自定義 TextComponent
s 的集合:
public class TextComponent : BindableObject
{
public static readonly BindableProperty TextProperty =
BindableProperty.Create(nameof(Text),
typeof(string),
typeof(TextComponent),
default(string));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
當文字元件的集合發生變化或者單獨元件的 Text
屬性發生變化時,我重建了基礎 Label
的 FormattedText
屬性。
我是如何在 XAML
中使用它的:
<ContentPage x:Name="Page"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:SuperForms.Controls;assembly=SuperForms.Controls"
x:Class="SuperForms.Samples.MultiComponentLabelPage">
<controls:MultiComponentLabel Margin="0,20,0,0">
<controls:MultiComponentLabel.Components>
<controls:TextComponent Text="Time"/>
<controls:TextComponent Text=": "/>
<controls:TextComponent Text="{Binding CurrentTime, Source={x:Reference Page}}"/>
</controls:MultiComponentLabel.Components>
</controls:MultiComponentLabel>
</ContentPage>
頁面的程式碼隱藏:
public partial class MultiComponentLabelPage : ContentPage
{
private string _currentTime;
public string CurrentTime
{
get { return _currentTime; }
set
{
_currentTime = value;
OnPropertyChanged();
}
}
public MultiComponentLabelPage()
{
InitializeComponent();
BindingContext = this;
}
protected override void OnAppearing()
{
base.OnAppearing();
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
CurrentTime = DateTime.Now.ToString("hh : mm : ss");
return true;
});
}
}