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

ibrsph3r  于 2023-04-07  发布在  其他
关注(0)|答案(6)|浏览(234)

我正在努力掌握WPF和MVVM,并取得了很好的进展。WPF和MVVM方面的事情进展顺利。
然而,XAML和数据绑定方面是另一回事:)
我该如何“禁用”一个按钮?
例如,我在视图模型中有一个CanClose属性,它决定了应用程序当前是否可以关闭。如果一个工作线程正在做一些事情,那么这个属性被设置为false,我想要么灰显按钮,要么通过某种绑定以某种方式在视觉上禁用Close按钮。
我该怎么做呢?
谢谢!

编辑-

可惜我只能接受一个答案。
这两个答案对我帮助很大。在肯特的帖子中,他更进一步解释了为什么你应该在应用程序中实现命令基础设施,而不是像我问的那样禁用按钮:
如何使用MVVM模式在WPF中“禁用”按钮?
我最初问题的答案是
如何使用MVVM模式在WPF中“禁用”按钮?

h9a6wy2h

h9a6wy2h1#

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

<Button IsEnabled="{Binding CanClose}"/>
tvz2xvvm

tvz2xvvm2#

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

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的更多信息。

b91juud3

b91juud33#

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

v9tzhpje

v9tzhpje4#

这也起作用:

查看

<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();
            }
        }
    }
dtcbnfnu

dtcbnfnu5#

这里的很多答案都是旧的,我不确定它们是否仍然是最新的。下面是我如何使用RelayCommand做到这一点的。我在.xaml中有一个保存保存按钮,它绑定到视图模型中的一个中继命令类的示例。中继命令还接受一个参数,该参数可以绑定到xaml中以传递对视图对象的引用。当视图模型中的一个属性发生变化时,我调用SaveCommand.RaiseCanExecuteChanged();来执行按钮,它是CanSave longic。
下面是视图模型:

namespace Projectname.viewmodels
{
    internal class addressPointVM : INotifyPropertyChanged, IDataErrorInfo
    {
       public addressPointVM() {
            SaveCommand = new RelayCommand<object>((parms) => DoSave(parms), parms => CanISave()); 
        }

        private bool CanISave()
        {
            return CanSave;
        }

        private void DoSave(object parms)
        {
             //ProWindow is my view that is calling the command
            (parms as ProWindow).DialogResult = true;
            (parms as ProWindow).Close(); ;
         }

        public RelayCommand<object> SaveCommand { get; private set; 
        private bool _canSave = false;
        //other elements alter this property and then call SaveCommand.RaiseCanExecuteChanged()
        public bool CanSave 
        {
            get
            {
                return _canSave;
            } 
            set
            {
                if (_canSave == value) return;
                _canSave = value;
            }
         }
    }
}

下面是RelayCommand类

public class RelayCommand<T> : ICommand
{
    Action<T> _TargetExecuteMethod;
    Func<T, bool> _TargetCanExecuteMethod;

    public RelayCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
    {
        _TargetExecuteMethod = executeMethod;
        _TargetCanExecuteMethod = canExecuteMethod;
    }

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

    bool ICommand.CanExecute(object parameter)
    {
        if (_TargetCanExecuteMethod != null)
        {
            T tparm = (T)parameter;
            return _TargetCanExecuteMethod(tparm);
        }
        if (_TargetExecuteMethod != null)
        {
            return true;
        }
        return false;
    }

    public event EventHandler CanExecuteChanged = delegate { };

    void ICommand.Execute(object parameter)
    {
        if (_TargetExecuteMethod != null)
        {
            _TargetExecuteMethod((T)parameter);
        }
    }
    
}

最后是xaml:

<Button Command="{Binding SaveCommand}" Style="{DynamicResource Esri_Button}" CommandParameter="{Binding ElementName=AddAddressPointWin}" Content="Save" Margin="5"/>
khbbv19g

khbbv19g6#

ViewModel文件中的更改:
public bool IsButtonEnabled { get { return _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}”

相关问题