2015-09-16 22 views
7

Tôi có một vấn đề ràng buộc dữ liệu trong một cái nhìn tùy chỉnh trong các hình thức Xamarin để xem mô hình của trang có chứa.Binding một Custom View Trong Xamarin.Forms

My Custom View là rất đơn giản, một cặp nhãn đại diện cho một cặp giá trị 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" Text="{Binding Key}" Grid.Column="0" HorizontalOptions="Start" /> 
     <Label x:Name="ValueLabel" Text="{Binding Value}" Grid.Column="1" HorizontalOptions="EndAndExpand" /> 
    </Grid> 
</ContentView> 

với mã sau:

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

này được tiêu thụ trong một trang như sau:

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

Vấn đề là chuỗi khóa được hiển thị như mong đợi, nhưng chuỗi giá trị thì không. Tôi đã cố gắng buộc một sự kiện PropertyChanged trên thuộc tính document_number, điều này không giúp được gì. Tôi cũng cố gắng thiết lập một cách rõ ràng các văn bản tài sản trên Nhãn trong setter của các thuộc tính Key/Value của giao diện tùy chỉnh:

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

Một lần nữa điều này không giúp đỡ, mã setter bao giờ có vẻ để thực hiện (I đặt một breakpoint vào nó và nó đã không đánh)

Nếu tôi thêm một ra khỏi sự kiểm soát hộp như một Label ràng buộc trực tiếp đến tài sản trong trang, điều này sẽ hiển thị một cách chính xác:

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

Can ai giải thích lý do tại sao điều này xảy ra (hoặc thay vì không xảy ra)?

Trả lời

20

Không gán các ràng buộc bên trong trong các điều khiển tùy chỉnh. Sử dụng điều này:

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> 

Thuộc tính xử lý (ví dụ: Giá trị) làm tham chiếu đến BindableProperty (ValueProperty). Nếu bạn làm điều gì đó bên trong Giá trị setter BindableProperty sẽ không được thông báo về nó VÀ ngược lại nếu bạn làm điều gì đó với BindableProperty (gán/thay đổi ValueProperty) - thuộc tính Value setter sẽ không được gọi.

Nếu bạn muốn xử lý PropertyChanged bạn có một ghi đè cho rằng (OnPropertyChanged) hoặc hành động (như thông số bổ sung khi tạo BindableProperty).

+0

Đó chính xác là những gì tôi cần, cảm ơn. Có thể có được một chút cồng kềnh cho một cái nhìn tùy chỉnh với rất nhiều thuộc tính bindable, nhưng tôi sẽ xem xét để refactor khi tôi nhận được đến thời điểm đó – MikeW

+0

Great câu trả lời. Nó hoạt động như một say mê. –

+0

Đó là một sự xấu hổ mà propertyChanged: từ BindableProperty là tĩnh, toàn bộ điểm cho thuộc tính tùy chỉnh nó được tái sử dụng và với phương pháp tĩnh này, bạn chỉ có thể sử dụng một yếu tố tùy chỉnh, nhưng giải pháp của bạn hoạt động như một quyến rũ – dpineda

0

tôi đã có thể có được điều này để làm việc bằng cách làm

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

và sau đó làm điều này trong xaml.cs cho quan điểm bạn đang sử dụng giao diện tùy chỉnh trong:

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

Đối một trường nhập, cho tôi vấn đề, tôi phải đảm bảo tham số defaultBindingMode được đặt thành TwoWay.

Các vấn đề liên quan