2015-09-16 30 views
7

Ho un problema di associazione dei dati in una vista personalizzata nei moduli Xamarin al modello di visualizzazione della pagina contenente.Associazione di una vista personalizzata in Xamarin.Forms

My Custom View è molto semplice, un paio di etichette che rappresentano una coppia chiave-valore:

<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> 

con il codice dietro:

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);} 
    } 
} 

Questo è consumato in una pagina come segue:

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

Il problema è che la stringa chiave viene visualizzata come previsto, ma la stringa del valore non lo è. Ho provato a forzare un evento PropertyChanged sulla proprietà document_number, questo non ha aiutato. Ho anche provato l'impostazione in modo esplicito la proprietà Text sulle etichette durante il setter delle proprietà chiave/valore della visualizzazione personalizzata:

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

Anche in questo caso non ha aiutato, il codice setter non sembra avere eseguito (I collocato un punto di interruzione su di esso e non è stato colpito)

Se aggiungo un fuori del controllo casella ad esempio un'etichetta legata direttamente alla struttura della pagina, questa viene visualizzata correttamente:

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

Può chiunque spiegare perché questo sta accadendo (o piuttosto non sta succedendo)?

risposta

20

Non assegnare i collegamenti internamente all'interno dei controlli personalizzati. Utilizzare questa:

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> 

proprietà Treat (ad esempio il valore.) Fatti al BindableProperty (ValueProperty). Se fai qualcosa all'interno del settaggio del valore BindableProperty non verrà notificato a questo proposito E di fronte se fai qualcosa con BindableProperty (assegna/cambia ValueProperty) - la proprietà Value setter non verrà chiamata.

Se si desidera gestire PropertyChanged, è necessario eseguire l'override per tale (OnPropertyChanged) o Azioni (come parametri aggiuntivi durante la creazione di BindableProperty).

+0

Questo è esattamente ciò di cui avevo bisogno, grazie. Potrebbe diventare un po 'ingombrante per una visualizzazione personalizzata con molte proprietà associabili, ma cercherò il refactor quando arrivo a questo punto – MikeW

+0

Ottima risposta. Esso funziona magicamente. –

+0

È un peccato che propertyChanged: da BindableProperty sia statico, l'intero punto per le proprietà personalizzate deve essere riutilizzato e con questo metodo statico è possibile utilizzare solo un elemento personalizzato, ma la soluzione funziona come un fascino – dpineda

0

sono stato in grado di ottenere questo al lavoro facendo

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

e poi fare questo nei xaml.cs per la vista che si sta utilizzando la visualizzazione personalizzata in:

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

Per un campo Entry, che mi ha dato problemi, ho dovuto assicurarmi che il parametro defaultBindingMode fosse impostato su TwoWay.

Problemi correlati