【问题标题】:how to disable the other functions when Button clicked in wpf C#在wpf C#中单击按钮时如何禁用其他功能
【发布时间】:2020-06-22 15:49:35
【问题描述】:
 I have a screen in WPF like that (WPF MVVM C#)I want to when I clicked the generate reports button.All of other functions will be disable.(without button) 

我该怎么做?我等待你的想法(就像在网格中)我可以像所有这些绑定 IsEnabled 一样做到这一点。但我不想那样做。

<CheckBox x:Name="IncludeEmployeesCheckBox" Content="Include All Employees" IsChecked="{Binding IncludeAllEmployees, Mode=TwoWay}" Margin="4" />
                <CheckBox Content="Exclude Weekends" IsChecked="{Binding ExcludeWeekends}" Margin="4" />
                <CheckBox Content="Exclude Former Employees" IsChecked="{Binding ExcludeFormerEmployees}" Margin="4" />
                <CheckBox Content="Exclude Public Holidays" IsChecked="{Binding ExcludePublicHolidays}" Margin="4" />
               
                <Button Content="Generate Reports" Command="{Binding GenerateReportsCommand}" Height="36" Margin="4" />

感谢您的所有帮助。

【问题讨论】:

  • 将所有这些控件包装在面板中并将 isEnabled 绑定到禁用属性。

标签: c# wpf mvvm disable


【解决方案1】:

假设您的报告生成函数运行的时间足够长以证明使用 async / await 模式的合理性,请为 GenerateReportsCommand 使用异步命令类。

public abstract class perCommandBase : ICommand
{
    // ICommand members
    public abstract bool CanExecute(object parameter);
    public abstract void Execute(object parameter);
    public event EventHandler CanExecuteChanged;

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
}

public class perRelayCommandAsync : perCommandBase, INotifyPropertyChanged
{
    private readonly Func<Task> _execute;
    private readonly Func<bool> _canExecute;

    public perRelayCommandAsync(Func<Task> execute) : this(execute, () => true)
    {
    }

    public perRelayCommandAsync(Func<Task> execute, Func<bool> canExecute)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }

    private bool _isExecuting;

    /// <summary>
    /// Is the command currently executing
    /// </summary>
    public bool IsExecuting
    {
        get => _isExecuting;
        set
        {
            _isExecuting = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsExecuting)));
            RaiseCanExecuteChanged();
        }
    }

    public override bool CanExecute(object parameter) => !IsExecuting && _canExecute();

    public override async void Execute(object parameter)
    {
        if (!CanExecute(parameter))
        {
            return;
        }

        IsExecuting = true;
        try
        {
            var response = await _execute()
                .ExecuteActionWithTimeoutAsync(ExecuteTimeOut)
                .ConfigureAwait(true);

            if (response.IsTimedOut)
            {
                OnTimeOutAction?.Invoke(response);
            }
            else if (response.IsError)
            {
                OnErrorAction?.Invoke(response);
            }
        }
        finally
        {
            IsExecuting = false;
        }
    }

    /// <summary>
    /// Timeout value for Execute invocation
    /// </summary>
    public TimeSpan ExecuteTimeOut { get; set; } = perTimeSpanHelper.Forever;

    /// <summary>
    /// Optional action to perform if Execute generates an error.
    /// </summary>
    public Action<perAsyncActionResponse> OnErrorAction { get; set; }

    /// <summary>
    /// Optional action to perform if Execute times out.
    /// </summary>
    public Action<perAsyncActionResponse> OnTimeOutAction { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
}

Button 将自动禁用,而 IsExecuting 为真,因为CanExecute 返回假。您还可以将其他控件的IsEnabledIsVisible 属性绑定到GenerateReportsCommand.IsExecuting

关于如何在我的blog post 上将命令的 CanExecute 链接到其他属性状态的更多建议。

【讨论】:

    【解决方案2】:

    如果您使用 MVVM 模式,最好保留一个与长时间运行的操作相关的布尔属性,例如您的 GenerateReportsCommand。然后,您可以使用该 bool 属性来隐藏/禁用 XAML 中的控件。

    例如:

    private bool busy;
    public bool Busy { get => this.busy; set { this.busy = value; OnPropertyChanged(); } }
    
    private async Task GenerateReportsAsync()
    {
      // Set the Busy flag at the beginning of your long running operation
      Busy = true;
    
      // ... do your report generation here, which may take a long time
    
      // Clear the Busy flag at the end of your long running operation
      Busy = false;
    }
    

    在您的 xaml 中(我在这里使用 StackPanel,但任何 UIElement 都可以使用其 IsEnabled 或 Visibility 属性:

    <StackPanel>
        <CheckBox/>
        <CheckBox/>
        <CheckBox/>
        <StackPanel.Style>
            <Style TargetType="StackPanel">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Busy}" Value="True">
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </StackPanel.Style>
    </StackPanel>
    <Button Content="Generate Reports" Command="{Binding GenerateReportsCommand}" Height="36" Margin="4" />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-02
      • 2015-06-20
      • 2019-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-23
      相关资源
      最近更新 更多