c# - Xamarin Forms 自定义控件 BindableProperty propertyChanged not Firing
问题描述
在标签中使用项目符号点时,尝试设置一个非常简单的自定义控件来处理对齐。问题是,传递到自定义控件的 Spans 没有被识别,并且内容没有被呈现(并且 propertyChanged 函数没有被触发)。我错过了什么?
XAML:
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="Sample.Controls.BulletPointItem"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ContentView.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label x:Name="BulletPoint" Text="•" />
<Label x:Name="LabelContent" Grid.Column="1" />
</Grid>
</ContentView.Content>
</ContentView>
代码隐藏:
[ContentProperty(nameof(Spans))]
public partial class BulletPointItem : ContentView
{
// todo add bindable props for bullet point size and color, or even which character to use as the bullet point!
public static readonly BindableProperty SpansProperty =
BindableProperty.Create(
nameof(Spans),
typeof(ObservableCollection<Span>),
typeof(BulletPointItem),
new ObservableCollection<Span>(),
BindingMode.OneWay,
propertyChanged: OnSpansChanged);
public BulletPointItem()
{
InitializeComponent();
}
public ObservableCollection<Span> Spans
{
get => (ObservableCollection<Span>)GetValue(SpansProperty);
set => SetValue(SpansProperty, value);
}
private static void OnSpansChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (BulletPointItem)bindable;
var newSpansValue = (ObservableCollection<Span>)newValue;
var formattedString = new FormattedString();
if (control == null)
return;
if (newSpansValue == null || newSpansValue.Count == 0)
{
control.LabelContent.FormattedText = formattedString;
return;
}
foreach (var span in newSpansValue)
{
formattedString.Spans.Add(span);
}
control.LabelContent.FormattedText = formattedString;
}
}
尝试使用:
<controls:BulletPointItem>
<Span Text="Span 1." />
<Span FontAttributes="Italic" Text="Span 2." />
</controls:BulletPointItem>
解决方案
原因: Spans是一个ObservableCollection。所以如果你想设置它的值,你应该在xaml中定义一个Collection,而不是直接列出Span。
解决方案:
我仍然建议您应该使用数据绑定,因为您已将其设置为BindableProperty。
<controls:BulletPointItem BackgroundColor="LightBlue" Spans="{Binding Spans}">
在代码后面或 ViewModel
public static readonly BindableProperty SpansProperty =
BindableProperty.Create(
nameof(Spans),
typeof(ObservableCollection<Span>),
typeof(BulletPointItem),
defaultValueCreator: bindable => new ObservableCollection<Span>(),
propertyChanged: OnSpansChanged);
public ObservableCollection<Span> spans { get; set; }
spans = new ObservableCollection<Span>() {
new Span(){Text="Span1" },
new Span(){Text="Span2",FontAttributes=FontAttributes.Italic }
};
当您想从中添加或删除项目时,这将更加灵活。
更新
当您完全从 XAML 设置 Spans 时。它会将项目添加到Spans中。但是只有在您为其设置新值时才会调用OnSpansChanged方法。因此,您可以在方法CollectionChanged中处理逻辑。每次将新项目添加到 Spans 时都会调用它。
public BulletPointItem()
{
InitializeComponent();
Spans.CollectionChanged += Spans_CollectionChanged;
}
// this method will been invoked 2 times if you add two span in xaml
private void Spans_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
var collection = sender as ObservableCollection<Span>;
//...
}
推荐阅读
- flutter - Dart 系统上的多个安装?
- c# - MSBuild - 一个包参考会干扰加载单独的任务
- python - 如何从从 CSV 文件加载的自定义联合数据集构建 federated_averaging_process
- r - 您如何在 R 中组织数据并运行多项式概率?
- html - 用css在悬停时选择两个跨度
- ios - 观察我的值是否在 Swift 中达到零?
- html - (引导程序 4)容器对移动设备没有响应
- multithreading - Delphi ISAPI:当前正在运行哪个 WebModule?
- javascript - 重启浏览器后记住 Cookie
- flutter - 如何在 http post 正文中发送大型 json 数据