自定义标签渲染器未设置绑定文本

时间:2018-01-15 08:16:52

标签: c# xamarin binding custom-renderer

我为标签创建了一个自定义渲染器,以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,因此NotaTestatanull,因此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);
        }

2 个答案:

答案 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;标签它不是,但现在它似乎正常。

谢谢!