2015-09-16 124 views
7

我有一個問題,將Xamarin表單中的自定義視圖中的數據綁定到包含頁面的視圖模型。在Xamarin.Forms中綁定自定義視圖

我的自定義視圖很簡單,一對代表一個鍵值對標籤:

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

與後面的代碼:

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

這是在一個頁面使用情況如下:

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

問題是Key字符串按預期顯示,但值字符串不是。 我試過在document_number屬性上強制一個PropertyChanged事件,這沒有幫助。 我也試圖明確設置自定義視圖的鍵/值屬性的二傳手在標籤上的Text屬性:

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

同樣,這並沒有幫助,二傳手代碼似乎從來沒有得到執行(我置於其上一個斷點,它未命中)

如果我添加一個開箱即用的控制,例如,直接綁定到頁面的屬性標籤,這將顯示正確:

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

任何人都可以解釋爲什麼會發生(或者)而不是發生)?

回答

20

不要在自定義控件內部分配綁定。使用此方法:

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> 

將屬性(例如Value)視爲對BindableProperty(ValueProperty)的引用。如果你在Value setter中做了一些事情,BindableProperty不會被通知它,反之如果你使用BindableProperty(賦值/更改ValueProperty)來做某事 - 屬性Value setter將不會被調用。

如果您想要處理PropertyChanged,那麼您可以對該(OnPropertyChanged)或Actions(作爲創建BindableProperty時的附加參數)進行覆蓋。

+0

這正是我所需要的,謝謝。對於具有許多可綁定屬性的自定義視圖可能會有點麻煩,但當我到達該點時,我會重新考慮 – MikeW

+0

很好的答案。它像一個魅力。 –

+0

PropertyChanged:從BindableProperty變成靜態的,整個定製屬性的重點將被重用,並且使用這種靜態方法,您只能使用一個自定義元素,但您的解決方案就像一個魅力 – dpineda

0

我能得到這個做

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

,然後在xaml.cs這樣的觀點您使用的自定義視圖的工作:

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

對於一個Entry字段,給我的問題,我不得不確保defaultBindingMode參數設置爲TwoWay。

相關問題