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 => AsyncCommand.Create(ValidateMandatory);
这将在每次访问ValidateMandatoryCommand
时创建一个新命令。 ValidateMandatoryCommand get; private set;
并在你的构造函数中初始化它
好的,谢谢。我会解决这个问题。但是您如何解释我的命令适用于按钮,而我的自定义按钮为空?
【参考方案1】:
如果从 Button 继承 View,则需要更改 BindableProperty 的名称。 Button 类已经有一个同名的属性。
【讨论】:
以上是关于Xamarin Forms 命令在自定义控件中始终为空的主要内容,如果未能解决你的问题,请参考以下文章
如何创建一个自定义控件,用户可以在 Xamarin.Forms 中添加任何类型的视图?
Xamarin.forms 自定义dropdownview控件
自定义控件的 Xamarin 数据绑定值计算为 Xamarin.Forms.Binding