【问题标题】:Xamarin Forms Command always null in custom controlXamarin Forms 命令在自定义控件中始终为空
【发布时间】: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; } 并在你的构造函数中初始化它
  • 好的,谢谢。我会解决这个问题。但是您如何解释我的命令适用于按钮,而我的自定义按钮为空?

标签: xamarin mvvm xamarin.forms icommand


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2018-10-12
    • 2020-01-30
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 2015-01-04
    • 2020-10-04
    相关资源
    最近更新 更多