【发布时间】:2018-06-23 20:31:45
【问题描述】:
我为标签创建了一个自定义渲染器,以 html 格式显示文本。
这是 iOS 的代码:
[assembly: ExportRenderer(typeof(LabelHtmlView), typeof(LabelHtmlCustomRenderer))]
namespace SgatMobileV2.iOS {
public class LabelHtmlCustomRenderer : LabelRenderer {
protected override void OnElementChanged(ElementChangedEventArgs<Label> e) {
base.OnElementChanged(e);
var View = (LabelHtmlView)Element;
if (View == null) return;
var Attribute = new NSAttributedStringDocumentAttributes();
var NsError = new NSError();
Attribute.DocumentType = NSDocumentType.HTML;
View.Text = string.IsNullOrEmpty(View.Text) ? string.Empty : View.Text;
Control.AttributedText = new NSAttributedString(View.Text, Attribute, ref NsError);
}
}
}
安卓代码:
[assembly: ExportRenderer(typeof(LabelHtmlView), typeof(LabelHtmlCustomRenderer))]
namespace SgatMobileV2.Droid.CustomRenderer {
public class LabelHtmlCustomRenderer : LabelRenderer {
public LabelHtmlCustomRenderer(Context context)
: base(context) {
}
protected override void OnElementChanged(ElementChangedEventArgs<Label> e) {
base.OnElementChanged(e);
var View = (LabelHtmlView)Element;
if (View == null) return;
Control.SetText(Html.FromHtml(View.Text.ToString(), FromHtmlOptions.ModeLegacy), TextView.BufferType.Spannable);
}
}
}
例如,我以这种方式使用 XAML 中的控件:
<view:LabelHtmlView Text="{Binding WoDett.NotaTestata}" Grid.Row="0" Grid.Column="1" HeightRequest="200"/>
其中WoDett 是一个复杂对象,NotaTestata 是一个包含 HTML 标记的字符串。
我已经调试了代码,在我设置WoDett对象之前调用了OnElementChanged,所以NotaTestata是null,所以XAML中的标签显示为空。
这种行为在 iOS 和 Android 上是相同的。
我有其他自定义渲染器,它们可以使用类似的逻辑正常工作,但这个标签不能。
我该如何解决这个问题?
编辑:
这是对象类中的NotaTestata 属性:
private string _NotaTestata = string.Empty;
public string NotaTestata {
get { return _NotaTestata; }
set {
_NotaTestata = value;
OnPropertyChanged(nameof(NotaTestata));
}
}
编辑 2:
ListView 中的相同自定义标签可以正常工作。
<ListView x:Name="ListaRigheWo" CachingStrategy="RetainElement" HasUnevenRows="True" SeparatorVisibility="Default" ItemsSource="{Binding ListaWORighe}">
ListaWORighe 是这样定义的:
public ObservableCollection<WorkOrderDettaglioListaRighe> ListaWORighe {
get {
ObservableCollection<WorkOrderDettaglioListaRighe> Lista = null;
if (WoDett.ListaWORighe != null) {
Lista = OrdinamentoRigheWo(WoDett.ListaWORighe);
}
return Lista;
}
set {
WoDett.ListaWORighe = new List<WorkOrderDettaglioListaRighe>(value);
RaisePropertyChanged(() => ListaWORighe);
}
}
自定义标签的使用方式如下:
<view:LabelHtmlView Text="{Binding DescrizioneIntervento}" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="4" Style="{StaticResource LblValore}" />
编辑 3:
根据用户@sme 的建议,我已经像这样修改了渲染器,添加了 OnElementPropertyChanged 方法的覆盖:
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) {
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Label.TextProperty.PropertyName) {
UpdateText();
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Label> e) {
base.OnElementChanged(e);
UpdateText();
}
private void UpdateText() {
var View = (LabelHtmlView)Element;
if (View == null) return;
var Attribute = new NSAttributedStringDocumentAttributes();
var NsError = new NSError();
Attribute.DocumentType = NSDocumentType.HTML;
View.Text = string.IsNullOrEmpty(View.Text) ? string.Empty : View.Text;
Control.AttributedText = new NSAttributedString(View.Text, Attribute, ref NsError);
}
【问题讨论】:
-
对于您的 WoDett 对象,NotaTestata 属性是否在 setter 中包含
OnPropertyChanged(nameof(NotaTestata))事件处理程序调用? -
是的,确实如此。我已经编辑了问题。
-
你设置
BindingContext了吗?我想你是否在绑定方面做错了什么? -
@Land 是的,我使用具有 AutoWireViewModel 属性的类将视图模型绑定到视图,并且视图上的所有其他绑定属性都可以正常工作。如果我使用普通标签,它会显示 HTML 标记。
标签: c# xamarin binding custom-renderer