2017-10-02 1 views
2

Ich füge eine Ressource über XAML in meine App.xaml. Diese Ressource ist ein impliziter Stil, der einem CustomControl zugewiesen wird. Das CustomControl enthält eine Beschriftung.Xamarin Forms BindableProperty Vor dem Konstruktor geändert

Um die TextColor dieses Labels festzulegen, erstelle ich eine bindbare Eigenschaft für das CustomControl und weise einen Wert mit dem impliziten Stil zu. Mit der PropertyChanged-Methode der BindableProperty setze ich die TextColor der Beschriftung in meinem CustomControl.

<Style TargetType="CustomControl" > 
    <Setter Property="InnerLabelTextColor" Value="Green" /> 
</Style> 

-

private static void InnerLabelTextColorChanged(BindableObject bindableObject, object oldValue, object newValue) 
{ 
    ((CustomControl)bindableObject).InnerLabel.TextColor = (Color)newValue; 
} 

Diese verwendet in XF 2.3.2.127 zu arbeiten, aber wenn ich zu XF aktualisiert 2.3.4.270 Ich begann eine Nullreferenceexception in der Custom bekommen - BindableProperty - InnerLabelTextColorChanged Methode.

Die PropertyChanged-Methode wird aufgerufen, bevor der Konstruktor ausgeführt wird. Mein InnerLabel ist null, wenn die PropertyChanged-Methode ausgeführt wird, die die NullReferenceException verursacht.

Ich frage mich, ob dieses Verhalten das angeforderte XF-Verhalten ist oder ob es ein Fehler ist?

Wenn es das angeforderte Verhalten ist, kann jemand den richtigen Weg zur Bewältigung dieser Situation bieten?

Danke!

Bearbeiten - individuelle Steuercodebeispiel

public sealed class CustomControl : ContentView 
{ 
    public static readonly BindableProperty InnerLabelTextColorProperty = 
     BindableProperty.Create("InnerLabelTextColor", typeof(Color), typeof(CustomControl), Color.Black, 
      BindingMode.OneWay, null, CustomControl.InnerLabelTextColorChanged, null, null, null); 


    public CustomControl() 
    { 
     this.InnerLabel = new Label(); 

     this.Content = this.InnerLabel; 
    } 


    public Label InnerLabel { get; set; } 


    public Color InnerLabelTextColor 
    { 
     get 
     { 
      return (Color)this.GetValue(CustomControl.InnerLabelTextColorProperty); 
     } 
     set 
     { 
      this.SetValue(CustomControl.InnerLabelTextColorProperty, value); 
     } 
    } 


    private static void InnerLabelTextColorChanged(BindableObject bindableObject, object oldValue, object newValue) 
    { 
     ((CustomControl)bindableObject).InnerLabel.TextColor = (Color)newValue; 
    } 
} 
+1

Ihren Steuercode benutzerdefinierte Put –

+0

@ZiyadGodil. Ich habe der Frage ein Codebeispiel hinzugefügt. –

Antwort

2

ich auf einem similar issue gearbeitet hatte irgendwann zurück, der einzige Unterschied in einem XAML-basierte Steuerung begegnet es wurde.

Ich denke, die Ursache für dieses Problem ist, dass (wenn wir einen global-impliziten Stil wie diese verwenden) der Basiskonstruktor versucht, diese bindbare Eigenschaft zu setzen, und da abgeleiteten Konstruktor immer noch auf seinen Zug wartet, treffen wir die Nullreferenz.

einfachste Weg, dies zu lösen wäre Binding zu verwenden, um Eigenschaften auf inneres Kind Kontrollen einzustellen (reference):

public CustomControl() 
{ 
    this.InnerLabel = new Label(); 

    // add inner binding 
    this.InnerLabel.SetBinding(Label.TextColorProperty, 
     new Binding(nameof(InnerLabelTextColor), 
        mode: BindingMode.OneWay, 
        source: this)); 

    this.Content = this.InnerLabel; 
} 
+0

Vielen Dank! Haben Sie eine Idee, ob dieses Xamarin Forms Verhalten beabsichtigt ist oder nicht? –

+0

Ich glaube nicht, dass es ein beabsichtigtes Verhalten ist - aber ein unglücklicher Nebeneffekt aufgrund einer schlechten Initialisierungslogik. Das Initialisieren einer abgeleiteten Klasseneigenschaft im Basiskonstruktor richtet sich gegen C# -Rahmenrichtlinien. https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/constructor – Ada