【发布时间】: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; }并在你的构造函数中初始化它 -
好的,谢谢。我会解决这个问题。但是您如何解释我的命令适用于按钮,而我的自定义按钮为空?
标签: xamarin mvvm xamarin.forms icommand