我为标签创建了一个自定义渲染器,以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);
}
}
}
Android代码:
[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标记的字符串。
我调试了代码,在设置OnElementChanged
对象之前调用了WoDett
,因此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);
}
答案 0 :(得分:1)
您的两个渲染器也应该覆盖OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
方法。创建新对象时调用OnElementChanged
,并在更改对象的属性时调用OnElementPropertyChanged
。我建议这样做(在OnElementPropertyChanged()
方法内部:
if (e.PropertyName == Label.TextProperty.PropertyName)
{
// the text was updated
Control.SetText(...);
}
答案 1 :(得分:0)
我通过以这种方式在XAML上添加Mode=TwoWay
来解决:
<view:LabelHtmlView Text="{Binding WoDett.NotaTestata, Mode=TwoWay}" Grid.Row="0" Grid.Column="1" />
我不知道为什么自定义标签是必要的,而对于&#34;正常&#34;标签它不是,但现在它似乎正常。
谢谢!