2015-09-16 17 views
7

Ich habe ein Problem beim Binden von Daten in einer benutzerdefinierten Ansicht in Xamarin-Formularen an das Ansichtsmodell der enthaltenden Seite.Binden einer benutzerdefinierten Ansicht in Xamarin.Forms

My Custom View ist sehr einfach, ein Paar von Etiketten ein Schlüsselwertpaar darstellt:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
      x:Class="KeyValueView"> 
    <Grid VerticalOptions="Start"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition /> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 

     <Label x:Name="KeyLabel" Text="{Binding Key}" Grid.Column="0" HorizontalOptions="Start" /> 
     <Label x:Name="ValueLabel" Text="{Binding Value}" Grid.Column="1" HorizontalOptions="EndAndExpand" /> 
    </Grid> 
</ContentView> 

mit dem Code hinter:

public partial class KeyValueView : ContentView 
{ 
    public KeyValueView() 
    { 
     InitializeComponent(); 
     this.VerticalOptions = LayoutOptions.Start; 
     this.BindingContext = this; 
    } 

    public static readonly BindableProperty ValueProperty = 
       BindableProperty.Create<KeyValueView, string>(w => w.Value, default(string)); 

    public string Value 
    { 
     get {return (string)GetValue(ValueProperty);} 
     set {SetValue(ValueProperty, value);} 
    } 

    public static readonly BindableProperty KeyProperty = 
     BindableProperty.Create<KeyValueView, string>(w => w.Key, default(string)); 

    public string Key 
    { 
     get {return (string)GetValue(KeyProperty);} 
     set {SetValue(KeyProperty, value);} 
    } 
} 

Dies in einer Seite verbraucht wird, wie folgt:

<views:KeyValueView Key="Order Number" Value="{Binding document_number}" /> 

Das Problem ist, dass die Key-Zeichenfolge wie erwartet angezeigt wird, aber die Zeichenfolge Wert nicht ist. Ich habe versucht, ein PropertyChanged-Ereignis für die Eigenschaft document_number zu erzwingen, das hat nicht geholfen. Ich habe auch versucht, auf den Etikett während des Setter der Schlüssel/Wert-Eigenschaften der benutzerdefinierten Ansicht die Eigenschaft Text explizit festlegen:

public string Key 
    { 
     get {return (string)GetValue(KeyProperty);} 
     set { 
      SetValue(KeyProperty, value); 
      KeyLabel.Text = value; 
     } 
    } 

Auch dies hat nicht geholfen, der Setter-Code nie ausgeführt werden scheint (I richtig einen Haltepunkt auf ihn gesetzt und es wurde nicht getroffen)

Wenn ich eine aus der Box Steuerung wie zum Beispiel ein Etikett gebunden direkt an der Immobilie auf der Seite hinzufügen, zeigt dies:

<Label Text="{Binding document_number}"/> 
<views:KeyValueView Key="Order Number" Value="{Binding document_number}" /> 

Kann jemand erklären, warum das passiert (oder eher nicht passiert)?

Antwort

20

Fügen Sie keine Bindungen intern in benutzerdefinierten Steuerelementen zu. Verwenden Sie diese Option:

public partial class KeyValueView : ContentView 
{ 
    public KeyValueView() 
    { 
     InitializeComponent(); 
     this.VerticalOptions = LayoutOptions.Start; 
    } 

    public static readonly BindableProperty ValueProperty = 
     BindableProperty.Create<KeyValueView, string>(w => w.Value, default(string)); 

    public string Value 
    { 
     get {return (string)GetValue(ValueProperty);} 
     set {SetValue(ValueProperty, value);} 
    } 

    public static readonly BindableProperty KeyProperty = 
     BindableProperty.Create<KeyValueView, string>(w => w.Key, default(string)); 

    public string Key 
    { 
     get {return (string)GetValue(KeyProperty);} 
     set {SetValue(KeyProperty, value);} 
    } 
    protected override void OnPropertyChanged(string propertyName) 
    { 
     base.OnPropertyChanged(propertyName); 

     if (propertyName == ValueProperty.PropertyName) 
     { 
      ValueLabel.Text = Value; 
     } 
     if (propertyName == KeyProperty.PropertyName) 
     { 
      KeyLabel.Text = Key; 
     } 
    } 
} 

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
      x:Class="KeyValueView"> 
    <Grid VerticalOptions="Start"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition /> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 

     <Label x:Name="KeyLabel" Grid.Column="0" HorizontalOptions="Start" /> 
     <Label x:Name="ValueLabel" Grid.Column="1" HorizontalOptions="EndAndExpand" /> 
    </Grid> 
</ContentView> 

Treat Eigenschaften (zB Wert.) Als Bezugnahmen auf BindableProperty (Valueproperty). Wenn Sie etwas tun, wird Value Setter BindableProperty nicht darüber benachrichtigt und umgekehrt, wenn Sie etwas mit BindableProperty tun (ValueProperty zuweisen/ändern) - Eigenschaft Value Setter wird nicht aufgerufen.

Wenn Sie mit PropertyChanged arbeiten möchten, haben Sie eine Überschreibung dafür (OnPropertyChanged) oder Aktionen (als zusätzliche Parameter beim Erstellen von BindableProperty).

+0

Das ist genau das, was ich brauchte, danke. Könnte für eine benutzerdefinierte Ansicht mit vielen bindefähigen Eigenschaften ein wenig umständlich werden, aber ich werde nach Refactor suchen, wenn ich an diesen Punkt komme – MikeW

+0

Große Antwort. Es wirkt wie ein Zauber. –

+0

Es ist eine Schande, dass propertyChanged: von BindableProperty statisch, der ganze Punkt für benutzerdefinierte Eigenschaften ist es wieder verwendet werden und mit dieser statischen Methode können Sie nur ein benutzerdefiniertes Element verwenden, aber Ihre Lösung funktioniert wie ein Charme – dpineda

0

Ich konnte dies, indem Sie

public KeyValueView() 
{ 
    InitializeComponent(); 
    this.VerticalOptions = LayoutOptions.Start; 
    this.Content.BindingContext = this; 
} 

und dann tut dies in dem xaml.cs für die Ansicht in denen Sie verwenden die benutzerdefinierte Ansicht zur Arbeit kommen:

public ParentView() 
{ 
    InitializeComponent(); 
    BindingContext = this; 
} 

Für ein Eingabefeld, das mir Probleme gab, musste ich sicherstellen, dass der Parameter defaultBindingMode auf TwoWay gesetzt wurde.

Verwandte Themen