2017-09-08 40 views
0

我對自定義控件上的綁定有一個奇怪的問題。我創建了一個自定義工具欄:自定義Xamarin.Forms控件中的綁定問題

public partial class TopToolbar 
{ 
    public static readonly BindableProperty BackCommandProperty = 
     BindableProperty.Create(nameof(BackCommand), typeof(ICommand), typeof(TopToolbar), propertyChanged: BackCommandChanged); 

    public ICommand BackCommand 
    { 
     get => (ICommand) GetValue(BackCommandProperty); 
     set => SetValue(BackCommandProperty, value); 
    } 

    public TopToolbar() 
    { 
     InitializeComponent(); 
    } 

    // for debug purposes only 
    protected override void OnBindingContextChanged() 
    { 
     base.OnBindingContextChanged(); 
     Debug.WriteLine(BindingContext); 
    } 

    // for debug purposes only 
    private static void BackCommandChanged(BindableObject bindable, object oldvalue, object newvalue) 
    { 
     Debug.WriteLine($"old: {oldvalue}, new: {newvalue}"); 
    } 
} 


<?xml version="1.0" encoding="UTF-8"?> 
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms" 
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
      x:Class="Core.Controls.TopToolbar" 
      x:Name="TopToolbarView" 
      BindingContext="{x:Reference TopToolbarView}" 
      Orientation="Vertical"> 
      <StackLayout Orientation="Horizontal" 
         HorizontalOptions="FillAndExpand" 
       <Image Source="{StaticResource Image.Toolbar.LeftArrow}"> 
        <Image.GestureRecognizers> 
         <TapGestureRecognizer Command="{Binding BackCommand}" /> 
        </Image.GestureRecognizers> 
       </Image> 
      </StackLayout> 

</StackLayout> 

我用它在頁面上以這樣的方式

<pages:ContentPage.Content> 
     <StackLayout BackgroundColor="{StaticResource LightGrayColor}" 
        Spacing="0" 
        Padding="0"> 
      <controls:TopToolbar Title="Master Data" BackCommand="{Binding MyBackCommand}" /> 

頁面BindingContext是一個視圖模型:

public class MyCustomersPageModel 
{ 
    public RelayCommand MyBackCommand { get; set; } 

    public MyCustomersPageModel() 
    { 
     MyBackCommand = // command creation; 
    } 
} 

從調試我知道一個控件的BindingContext設置正確(OnBindingContextChanged)自己(TopToolbar對象)兩次 - 第一次當沒有孩子六並且在添加之後第二次。我已檢查BindingContext在所有子控件中都正確傳播。

不幸的是,BackCommand根本沒有綁定。即使一次也不會調用TopToolbar.BackCommand的setter。

有趣的是,當我更換一個控制在綁定的一切直接設置Souce設置BindingContext正常工作:

<?xml version="1.0" encoding="UTF-8"?> 
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms" 
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
      x:Class="Core.Controls.TopToolbar" 
      x:Name="TopToolbarView" 
      Orientation="Vertical"> 
      <StackLayout Orientation="Horizontal" 
         HorizontalOptions="FillAndExpand" 
       <Image Source="{StaticResource Image.Toolbar.LeftArrow}"> 
        <Image.GestureRecognizers> 
         <TapGestureRecognizer Command="{Binding Source={x:Reference TopToolbarView}, Path=BackCommand}" /> 
        </Image.GestureRecognizers> 
       </Image> 
      </StackLayout> 

</StackLayout> 

任何線索我做錯了什麼?

回答

1

它按預期工作。我會建議使用Source

在第一種情況下,當你TopToolbar給自己設定BindingContext,然後我會想象這將是事件的順序:

  1. 自定義控制構造,BindingContext通過參考分配給自己。

  2. 頁面實例已創建,控件添加到它。

  3. 當頁面的BindingContext被設置,通過財產繼承的權力,所有它的子控件'BindingContext被更新。

  4. 此時,您的自定義控件的BindingContext仍然引用自身as value-propagation doesn't override manually set context

  5. 因此,綁定<controls:TopToolbar BackCommand="{Binding MyBackCommand}"失敗,因爲此綁定將嘗試在其綁定上下文上查找MyBackCommand

但是,在第二種情況下,當您指定的Tapped命令結合SourceTopToolbar,那麼這應該是事件的順序:構建

  1. 自定義控制,BindingContext爲空。

  2. 頁面實例已創建,控件添加到它。

  3. 當設置頁面的BindingContext時,通過繼承屬性的權力,它的所有子控件'BindingContext已更新,包括您的自定義控件。

  4. 此時您的自定義控件的BindingContext現在引用MyCustomersPageModel。因此在<controls:TopToolbar BackCommand="{Binding MyBackCommand}"中的綁定被適當地設置。

  5. 現在Tapped結合不關心BindingContext,因爲它的來源是明確指出,這是家長控制TopToolbar - 又將其BackCommand被綁定到視圖模型的命令。因此,view-model命令現在綁定到手勢識別器的Tapped命令。它的工作原理!

+0

謝謝您的詳細解釋! – Marek

+1

太棒了!我希望答案是有幫助的。 – Ada