【问题标题】:CanExecute() not enabling button when condition is met满足条件时 CanExecute() 不启用按钮
【发布时间】:2014-09-13 23:03:02
【问题描述】:

我有一个非常简单的应用程序,其中包含 TextBoxButton。当TextBox 中输入的文本长度超过 5 个字符时,将启用该按钮。这是我的 ViewModel 的代码:

private string _text { get; set; }
public string Text
{
    get { return _text; }
    set
    {
        _text = value;
        OnPropertyChanged("Text");
    }
}

private ICommand _buttonCommand;
public ICommand ButtonCommand
{
    get
    {
        if (_buttonCommand == null)
        {
            _buttonCommand = new RelayCommand(
                param => this.ButtonCommandExecute(), 
                param => this.ButtonCommandCanExecute()
            );
        }
        return _buttonCommand;
    }
}

private bool ButtonCommandCanExecute()
{
    if (this.Text.Length < 5)
    {
        return false;
    }
    else
    {
        return true;
    }
}

private void ButtonCommandExecute()
{
    this.Text = "Text changed";
}

public MainWindowViewModel()
{
    //
}

TextBoxButton 使用此 XAML 绑定:

<Button Content="Button" HorizontalAlignment="Left" 
                Margin="185,132,0,0" VerticalAlignment="Top" Width="120"
                Command="{Binding Path=ButtonCommand}" />

<TextBox HorizontalAlignment="Left" Height="23" 
         Margin="185,109,0,0" TextWrapping="Wrap" 
         Text="{Binding Path=Text, Mode=TwoWay}" VerticalAlignment="Top" Width="120"/>

DataContext 似乎设置正确,但这里只是因为我是 WPF 初学者:

private MainWindowViewModel view_model;

public MainWindow()
{
    InitializeComponent();

    view_model = new MainWindowViewModel();

    this.DataContext = view_model;
}

当我输入TextBox 时,Button 永远不会启用。

【问题讨论】:

  • 如果您跳出 TextBox,它是否正确启用/禁用? TextBox.Text 的默认绑定模式是 OnLostFocus,因此在 TextBox 失去焦点之前,数据不会保留回您的 VM。要更改它,您可以将绑定Mode 属性设置为PropertyChanged。另外,您使用的是什么类型的 RelayCommand?如果是 MVVM 轻型中继命令,那么它应该在属性更改时自动引发CanExecuteChanged 并重新查询CanExecute,但并非所有中继命令都是这样。
  • 这也是一个问题,非常感谢 Rachel。

标签: c# wpf relaycommand


【解决方案1】:

ICommand 接口的一些实现有特殊的方法来通知“CanExecute”是否发生了变化。 RelayCommand类(MVVM Light)有这样的方法。

private string _text;
public string Text
{
    get { return _text; }
    set
    {
        _text = value;
        OnPropertyChanged("Text");

        // There is a special RelayCommand method to notify "CanExecute" changed.
        // After this call, the "CanExecute" state is "re-evaluated" automatically by binding using CanExecute Func passed into RelayCommand constructor.
        _buttonCommand.RaiseCanExecuteChanged();
    }
}

private RelayCommand _buttonCommand;
public ICommand ButtonCommand
{
    get
    {
        if (_buttonCommand == null)
        {
            _buttonCommand = new RelayCommand(
                param => this.ButtonCommandExecute(), 
                param => this.ButtonCommandCanExecute()
            );
        }
        return _buttonCommand;
    }
}

这个问题很有用:What is CanExecuteChanged for?

【讨论】:

  • 这是正确的答案,因为它允许 ICommand 按设计工作并且不需要额外的属性或绑定。
【解决方案2】:

实际上你必须使 Bool 属性绑定到按钮控件的 IsEnabled 属性。当您在 Textbox 中的文本超过五个字符时,将此属性设置为 true - 您必须在 Setter of Text 属性中执行此操作,因为这是您在 TextBox 中键入时调用的内容。

关于命令的基本知识:- 这些基本上是为了向 C# 代码报告例如 Clicks 事件,比如您的 Viewmodel/Page.cs 。这样您就可以执行一些任务。它与按钮的启用和禁用无关。

遵循代码:-

private string _text { get; set; }
public string Text
{
    get { return _text; }
    set
    {
        _text = value;

        if(_text.Length  > 5)
        // Enable button here
        // and command does not enable Buttons they are basically report the clicks events.
        IsButtonEnabled = true;

        OnPropertyChanged("Text");
    }
}

为启用按钮创建名为 IsButtonEnabled 的 Bool 类型属性并将此属性绑定到 Xaml 中的 Button。

private bool _IsButtonEnabled { get; set; }
public bool IsButtonEnabled
{
    get { return _IsButtonEnabled ; }
    set
    {
        _IsButtonEnabled = value;
        OnPropertyChanged("IsButtonEnabled");
    }
}

在 Xaml 中:-

<Button Content="Button" HorizontalAlignment="Left" 

             IsEnabled="{Binding IsButtonEnabled}"

            Margin="185,132,0,0" VerticalAlignment="Top" Width="120"
            Command="{Binding Path=ButtonCommand}" />

【讨论】:

  • 老兄,非常感谢!我做了你所说的,因为它是有道理的,但你能详细说明 IsButtonEnabled 的绑定吗?我是否将此绑定到我的 Button 的 IsEnabled 属性?
  • @user3761858 是的,兄弟。我在ans的底部添加了一个代码。 :)
  • 注意:不需要额外的属性。将命令(字段)存储为RelayCommand,然后在OnPropertyChanged("Text") 之后调用RelayCommand.RaiseCanExecuteChanged();
  • @SergeyBrunov 你的意思是说如果之前禁用按钮,它将启用按钮?
  • @SergeyBrunov 谢谢我不知道 :) 我试试看。只是去睡觉。现在使用我的标签。
【解决方案3】:

尝试对您的代码进行小修改,并告诉我它是否有效:

private string _text { get; set; }
public string Text
{
    get { return _text; }
    set
    {
        _text = value;
        OnPropertyChanged("Text");
        ButtonCommandCanExecute();
    }
}

private ICommand _buttonCommand;
public ICommand ButtonCommand
{
    get
    {
        if (_buttonCommand == null)
        {
            _buttonCommand = new RelayCommand(
                param => this.ButtonCommandExecute(), 
                param => this.ButtonCommandCanExecute()
            );
        }
        return _buttonCommand;
    }
}

private bool ButtonCommandCanExecute()
{
    if (this.Text.Length < 5)
    {
        return false;
    }
    else
    {
        return true;
    }
}

private void ButtonCommandExecute()
{
    this.Text = "Text changed";
}

public MainWindowViewModel()
{
    //
}

【讨论】:

  • 这行不通:- 启用/禁用按钮的代码在哪里?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-11
  • 1970-01-01
  • 1970-01-01
  • 2019-03-29
  • 2020-08-05
  • 2021-09-24
  • 1970-01-01
相关资源
最近更新 更多