如何使用 MVVM 模式“禁用”WPF 中的按钮?

Posted

技术标签:

【中文标题】如何使用 MVVM 模式“禁用”WPF 中的按钮?【英文标题】:How does one "disable" a button in WPF using the MVVM pattern? 【发布时间】:2011-03-29 10:45:06 【问题描述】:

我正在尝试掌握 WPF 和 MVVM 并取得了不错的进展。 WPF 和 MVVM 方面进展顺利。

但是,XAML 和数据绑定方面完全是另一回事 :)

我将如何“禁用”按钮?

例如,我的视图模型中有一个 CanClose 属性,用于确定当前是否可以关闭应用程序。如果工作线程停止执行某项操作,则此属性设置为 false,我想将按钮设为灰色,或者通过某种绑定以某种方式在视觉上禁用关闭按钮。

我该怎么做呢?

谢谢!

编辑 -

可惜我只能接受一个答案。

这两个答案对我帮助很大。在 Kent 的帖子中,他更进一步解释了为什么应该在应用程序中实现命令基础架构,而不是按照我要求的方式禁用按钮:

How does one "disable" a button in WPF using the MVVM pattern?

我原来的问题的答案:

How does one "disable" a button in WPF using the MVVM pattern?

【问题讨论】:

【参考方案1】:

只需将 Button 的 IsEnabled 属性绑定到 CanClose:

<Button IsEnabled="Binding CanClose"/>

【讨论】:

不可能,真的那么容易吗?我不知道我怎么能忽略这一点。让我试试看。 谢谢,我不敢相信我竟然忽略了这么简单的问题答案。 值得注意的是,如果您采用 MVVM 方法并且您正在使用 Commands 及其 CanExecute 属性,根据微软文档,您不应该使用 IsEnabled 属性。它在文档中并标记为重要:docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/…【参考方案2】:

通过使用命令模式。在您的视图模型中:

public class MyViewModel : ViewModel

    private readonly ICommand someCommand;

    public MyViewModel()
    
        this.someCommand = new DelegateCommand(this.DoSomething, this.CanDoSomething);
    

    public ICommand SomeCommand
    
        get  return this.someCommand; 
    

    private void DoSomething(object state)
    
        // do something here
    

    private bool CanDoSomething(object state)
    
        // return true/false here is enabled/disable button
    

在您的 XAML 中:

<Button Command="Binding SomeCommand">Do Something</Button>

阅读this post 以了解有关DelegateCommand 的更多信息。

【讨论】:

不错的链接,感谢您提供的信息。我会在今天下午有更多空闲时间时阅读整本书。我认为 DelegateCommand 是您自己实现的命令模式,还是我在 .net 框架中缺少的东西? @IanP DelegateCommand 是 Prism 的一部分,这似乎是当今编写 WPF 应用程序的实际方式...... 嗯.. 不知道 DelegateCommand 做了什么,这并没有像我希望的那样帮助我.. 哈哈 啊——Kent 在他的博客上有一个示例 DelegateCommand 实现的链接。再次感谢! 不幸的是,链接已经失效,这使得这个答案毫无用处。【参考方案3】:

如果返回 ICommand 的 CanExecute 值为 false,则 Button 将被禁用。所以无论你的按钮绑定到什么命令,当你想禁用它时,看看你是否可以返回 CanExecute 一个 false 值。

【讨论】:

【参考方案4】:

这也有效:

查看

        <Button>
            <Button.Style>
                <Style>
                    <Setter Property="Content" Value="Scream" />
                    <Style.Triggers>
                        <DataTrigger Binding="Binding btnEnabled" Value="True">
                            <Setter Property="IsEnabled" Value="True" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>

视图模型

    private bool _btnEnabled;
    public bool btnEnabled
    
        get  return _btnEnabled; 
        set
        
            if (_btnEnabled != value)
            
                _btnEnabled = value;
                OnPropertyChanged();
            
        
    

【讨论】:

【参考方案5】:

ViewModel 文件的变化:

公共布尔 IsButtonEnabled 得到 返回 _isButtonEnabled;

set

    if (_isButtonEnabled == value)
    
        return;
    

    _isButtonEnabled = value;
    OnPropertyChanged("IsButtonEnabled");



public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    

按钮的 XAML 文件中的更改:IsEnabled="Binding IsButtonEnabled"

【讨论】:

以上是关于如何使用 MVVM 模式“禁用”WPF 中的按钮?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MVVM 模式中从页面导航到 WPF 中的页面?没有棱镜的概念[重复]

使用 MVVM 和视图模型通信的 WPF 窗口模式对话框

如何从作为wpf mvvm模式中的窗口打开的视图模型中关闭用户控件?

禁用 WPF MVVM 中 DataGrid 中自动生成的列的排序

如何在WPF中动态创建布局(MVVM模式)

使用 MVVM 在 WPF 中创建新窗口的最佳方法