Binding 自定义Xamarin.Forms控件中的绑定问题

Binding 自定义Xamarin.Forms控件中的绑定问题,binding,xamarin.forms,Binding,Xamarin.forms,我对自定义控件的绑定有一个奇怪的问题。我创建了一个自定义工具栏: public partial class TopToolbar { public static readonly BindableProperty BackCommandProperty = BindableProperty.Create(nameof(BackCommand), typeof(ICommand), typeof(TopToolbar), propertyChanged: BackComma

我对自定义控件的绑定有一个奇怪的问题。我创建了一个自定义工具栏:

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>
通过调试,我知道控件的
BindingContext
被正确地设置为自身(
TopToolbar
object),第一次是在没有子视图时,第二次是在添加子视图后。我已经检查了
BindingContext
是否在所有子控件中正确传播

不幸的是,
BackCommand
根本没有绑定。
TopToolbar.BackCommand
的setter甚至不会被调用一次

有趣的是,当我将在控件上设置
BindingContext
替换为直接在绑定中设置
Souce
时,一切正常:

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


它正在按预期工作。我建议使用
Source

在第一种情况下,当您将
TopToolbar
上的
BindingContext
设置为自身时,我会想象这将是一系列事件:

  • 构建自定义控件时,
    BindingContext
    通过引用分配给self

  • 页面实例被创建,控件被添加到其中

  • 当页面的
    BindingContext
    被设置时,通过属性继承的能力,它的所有子控件的
    BindingContext
    都会被更新

  • 此时,自定义控件的
    BindingContext
    仍在引用自身


  • 因此,binding
    它正按预期工作。我建议使用
    Source

    在第一种情况下,当您将
    TopToolbar
    上的
    BindingContext
    设置为自身时,我会想象这将是一系列事件:

  • 构建自定义控件时,
    BindingContext
    通过引用分配给self

  • 页面实例被创建,控件被添加到其中

  • 当页面的
    BindingContext
    被设置时,通过属性继承的能力,它的所有子控件的
    BindingContext
    都会被更新

  • 此时,自定义控件的
    BindingContext
    仍在引用自身


  • 因此,binding
    感谢您的详细解释!伟大的我希望答案是有帮助的。谢谢你的详细解释!伟大的我希望答案是有帮助的。
    
    public class MyCustomersPageModel
    {
        public RelayCommand MyBackCommand { get; set; }
    
        public MyCustomersPageModel()
        {
            MyBackCommand = // command creation;
        }
    }
    
    <?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>