Xamarin Forms 命令在自定义控件中始终为空

Posted

技术标签:

【中文标题】Xamarin Forms 命令在自定义控件中始终为空【英文标题】:Xamarin Forms Command always null in custom control 【发布时间】:2020-08-25 00:55:51 【问题描述】:

我尝试创建一个用户控件。用户控件将是一个显示加载程序的按钮。

我尝试将绑定命令从我的页面传递到我的控件

我的 XAML 页面是:

                <sharedviews:ButtonLoader TextLabel="extensions:Translate Save"   BackgroundColorButton="StaticResource RedColor" HeightRequest="50" HorizontalOptions="Center" Animation="Cupertino" TextColorIndicator="White" 
                                          TextColorLabel="White"  VerticalOptions="End" Command="Binding ValidateMandatoryCommand" TextWaiting="extensions:Translate Saving..." />

                <Button HeightRequest="50" WidthRequest="150" VerticalOptions="End" Margin="0,10,0,0"  HorizontalOptions="Center"
                    Style="StaticResource ValidButtonStyle" FontSize="15" Padding="5"
                    Text="extensions:Translate Next"
                            Command="Binding ValidateMandatoryCommand" />

当我在标准按钮中使用命令 ValidateMandatoryCommand 时效果很好。当我在自定义按钮 (sharedviews:ButtonLoader) 中使用它时,它始终为空。这证实了我的命令 ValidateMandatoryCommand 运行良好。

我的自定义按钮的 XAML 如下所示:

 <ContentView.Content>
    <Grid>
        <buttons:SfButton x:Name="btn" Clicked="btn_Clicked" CornerRadius="30" HorizontalOptions="Center" VerticalOptions="Center">
            <buttons:SfButton.Content>
                <StackLayout Orientation="Horizontal" Margin="10">
                    <busyindicator:SfBusyIndicator IsVisible="False" x:Name="busyIndicator" AnimationType="Cupertino" IsBusy="True" TextColor="White" WidthRequest="40" ViewBoxWidth="40"/>
                    <Label x:Name="labelLoader" Text="Loading..." FontSize="15" VerticalTextAlignment="Center" HorizontalOptions="CenterAndExpand" TextColor="White" />
                </StackLayout>
            </buttons:SfButton.Content>
        </buttons:SfButton>
    </Grid>
</ContentView.Content>

我的命令的按钮加载器的 C# 代码是


     public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(ButtonLoader), default(ICommand), defaultBindingMode: BindingMode.TwoWay);
        public ICommand Command
        
            get
            
                return (ICommand)GetValue(CommandProperty);
            

            set
            
                SetValue(CommandProperty, value);
            
        

     private async void btn_Clicked(object sender, EventArgs e)
        
            labelLoader.Text = TextWaiting;
            busyIndicator.IsBusy = true;
            busyIndicator.IsVisible = true;

            //if (Command != null) <= //**Always NULL**
            //
                await Task.Run(() => 
                    Command.Execute(null);
                );

            //


            busyIndicator.IsVisible = false;
            busyIndicator.IsBusy = false;
            labelLoader.Text = TextLabel;
        

根据 cmets 进行编辑

我的 ValidateMandatoryCommand 定义为:

public ICommand ValidateMandatoryCommand => AsyncCommand.Create(ValidateMandatory);

    private async Task ValidateMandatory()
      

还有异步命令

   public class AsyncCommand : ICommand

    public event EventHandler CanExecuteChanged;

    private readonly ICommand _command;

    protected AsyncCommand(ICommand command)
    
        _command = command;
        command.CanExecuteChanged += (sender, args) => CanExecuteChanged.InvokeSafely(sender, args);
    

    public bool CanExecute(object parameter)
    
        return _command.CanExecute(parameter);
    

    public void Execute(object parameter)
    
        _command.Execute(parameter);
    

    public static AsyncCommand Create(Func<System.Threading.Tasks.Task> func)
    
        return new AsyncCommand(new Command(async () => await func()));
    

【问题讨论】:

嗯 LGTM。您能否向我们展示您的视图模型(您的 BindingContext / 分别包含 ValidateMandatoryCommand 的类)以及您是如何设置它的? 真的无法重现。您还可以显示自定义视图的完整来源吗? 我看到您正在使用 BindingMode.TwoWay,这在某些情况下可能会导致覆盖 ViewModel 的命令,因此也可以在按钮的代码隐藏和页面的视图模型中检查这一点。此外,我建议使用异步命令的这种实现,以避免您的任何静默异常。 github.com/brminnick/AsyncAwaitBestPractices/blob/master/Src/… @xerx 说了什么。另外:我不建议使用ValidateMandatoryCommand =&gt; AsyncCommand.Create(ValidateMandatory); 这将在每次访问ValidateMandatoryCommand 时创建一个新命令。 ValidateMandatoryCommand get; private set; 并在你的构造函数中初始化它 好的,谢谢。我会解决这个问题。但是您如何解释我的命令适用于按钮,而我的自定义按钮为空? 【参考方案1】:

如果从 Button 继承 View,则需要更改 BindableProperty 的名称。 Button 类已经有一个同名的属性。

【讨论】:

以上是关于Xamarin Forms 命令在自定义控件中始终为空的主要内容,如果未能解决你的问题,请参考以下文章

如何创建一个自定义控件,用户可以在 Xamarin.Forms 中添加任何类型的视图?

Xamarin.forms 自定义dropdownview控件

自定义控件的 Xamarin 数据绑定值计算为 Xamarin.Forms.Binding

Xamarin Forms - 内容未在 stackLayout 中垂直居中对齐

Xamarin Forms - 在页面打开时填充自定义控件

Xamarin.Forms 将自定义控件创建为网格布局中的一行