Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我是否可以扩展command类,使绑定到它的按钮自动禁用?_C#_Xaml_Mvvm_Xamarin.forms - Fatal编程技术网

C# 我是否可以扩展command类,使绑定到它的按钮自动禁用?

C# 我是否可以扩展command类,使绑定到它的按钮自动禁用?,c#,xaml,mvvm,xamarin.forms,C#,Xaml,Mvvm,Xamarin.forms,在我的应用程序中,我将按钮绑定到带有“MVVM”的命令。 我的命令实现如下: public Command CommandLoadStuff { get { return new Command(async () => { await DoLongStuff(); });

在我的应用程序中,我将按钮绑定到带有“MVVM”的命令。 我的命令实现如下:

        public Command CommandLoadStuff
        {
            get
            {
                return new Command(async () =>
                {
                    await DoLongStuff();
                });
            }
        }
问题是这些命令是异步的,用户可以多次单击它们,从而导致代码也执行多次

作为第一种方法,我使用CanExecute:

        public Command CommandLoadStuff
        {
            get
            {
                return new Command(async () =>
                {
                    AppIsBusy = true;
                    await DoLongStuff();
                    AppIsBusy = false;
                },() => !AppIsBusy);
            }
        }
现在我想知道是否有比单独处理每个命令的CanExecute更好的方法了

由于我每次都用“new”初始化命令,我想知道类“command”是否不能相应地扩展。它应该在CanExecute的使用寿命期间阻止第二次单击按钮(可能在构造函数中?),并在命令执行完成后释放它。(可能在Dispose功能中?)


有没有办法实现这一点?

您可以使用
IsEnabled
属性使
按钮无法单击。
就像下面的代码一样

<Button 
    Text="click"
    Command={Binding Button1Command}
    IsEnabled={Binding AreButtonsEnabled} />

您可以使用
IsEnabled
属性使
按钮
无法单击。 就像下面的代码一样

<Button 
    Text="click"
    Command={Binding Button1Command}
    IsEnabled={Binding AreButtonsEnabled} />

据我所知,以这种方式扩展class命令是不可能的,因为
Execute
是非虚拟的,您必须将
Execute
操作传递给构造函数。无论如何,还是有办法的<代码>命令
源自具有以下接口的ICommand

公共接口ICommand
{
事件处理程序CanExecuteChanged;
无效执行(对象数据);
布尔CanExecute(对象数据);
}
您可以创建一个类
AsyncBlockingCommand
(或其他任何类型),该类将返回
CanExecute
中的相应值,具体取决于异步方法是否仍在运行(我知道
async void
方法存在问题,请小心处理)

公共类AsyncBlockingCommand:ICommand
{
bool_canExecute=true;
履行职能;
公共异步阻塞命令(Func-toExecute)
{
_toExecute=toExecute;
}
公共事件处理程序CanExecuteChanged;
公共异步void执行(对象数据)
{
_canExecute=false;
RaiseCanExecuteChanged();
等待执行();
_canExecute=true;
RaiseCanExecuteChanged();
}
公共布尔CanExecute(对象数据)=>\u CanExecute;
private void RaiseCanExecuteChanged()的定义
{
CanExecuteChanged?.Invoke(此为EventArgs.Empty);
}
}

在执行异步方法之前,
\u canExecute
设置为
false
,并引发
CanExecuteChanged
。这样,您的
按钮
将收到
CanExecute
已更改并禁用自身的通知。反之亦然,在异步方法被调用之后。(可能必须在主线程上调用
raisecancecutechanged

以这种方式扩展class命令是不可能的,因为
Execute
是非虚拟的,您必须将
Execute
操作传递给构造函数。无论如何,还是有办法的<代码>命令源自具有以下接口的ICommand

公共接口ICommand
{
事件处理程序CanExecuteChanged;
无效执行(对象数据);
布尔CanExecute(对象数据);
}
您可以创建一个类
AsyncBlockingCommand
(或其他任何类型),该类将返回
CanExecute
中的相应值,具体取决于异步方法是否仍在运行(我知道
async void
方法存在问题,请小心处理)

公共类AsyncBlockingCommand:ICommand
{
bool_canExecute=true;
履行职能;
公共异步阻塞命令(Func-toExecute)
{
_toExecute=toExecute;
}
公共事件处理程序CanExecuteChanged;
公共异步void执行(对象数据)
{
_canExecute=false;
RaiseCanExecuteChanged();
等待执行();
_canExecute=true;
RaiseCanExecuteChanged();
}
公共布尔CanExecute(对象数据)=>\u CanExecute;
private void RaiseCanExecuteChanged()的定义
{
CanExecuteChanged?.Invoke(此为EventArgs.Empty);
}
}

在执行异步方法之前,
\u canExecute
设置为
false
,并引发
CanExecuteChanged
。这样,您的
按钮
将收到
CanExecute
已更改并禁用自身的通知。反之亦然,在异步方法被调用之后。(可能必须在主线程上调用
raisecancecutechanged

一些想法:
BebinInvokeOnMainThread
是从应该已经在主线程上的方法调用的。因此,我认为没有必要把它放在哪里。此外,您希望避免在主线程上执行长时间运行的计算。一些想法:
BebinInvokeOnMainThread
是从应该已经在主线程上的方法调用的。因此,我认为没有必要把它放在哪里。此外,您希望避免在主线程上进行长时间运行的计算。非常感谢!这与我做的实验类似,但我忘记等待执行,因此我的命令立即再次启用!你的剪发会解决我的问题。谢谢!:)->我编辑了你的文章,因为调用函数需要两个参数。CanExecuteChanged?.Invoke(此为EventArgs.Empty);当然,事件需要参数。谢谢你的编辑,非常感谢!这与我做的实验类似,但我忘记等待执行,因此我的命令立即再次启用!你的剪发会解决我的问题。谢谢!:)->我编辑了你的文章,因为调用函数需要两个参数。CanExecuteChanged?.Invoke(此为EventArgs.Empty);当然,事件需要参数