2

我有一个文本框供用户输入字符串,还有一个“添加”按钮可以使用该值执行一些任务。我向 DelegateCommand 添加了一个 CanExecute 方法,以便该按钮仅在框中有文本时才起作用。

然而,它一直被禁用——即使条件为真。在框中键入不会启用按钮。

<TextBox Text="{Binding BuildEntryText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Command="{Binding AddBuildCommand}" Content="Add" />

this.AddBuildCommand = new DelegateCommand(() => this.AddBuild(), () => this.CanAddBuild());

private bool CanAddBuild()
{
    if (this.BuildEntryText != null)
    {
        return true;
    }
    else
    {
        return false;
    }
}

我以前发生过这种情况(并不总是使用相同类型的控件),通常我只会删除 CanExecute 并将其更改为操作方法中的“if”检查。不过,这一次,我实际上必须让它工作并以“正确”的方式将按钮变灰。

任何见解将不胜感激。提前致谢。

更新:

我已将 RaiseCanExecuteChanged 添加到 BuildEntryText 属性的设置部分。现在按钮开始禁用并在第一次输入文本时启用。但是,即使在删除文本或通过添加功能清除框后,它仍保持启用状态。

public string BuildEntryText
{
    get
    {
        return this.buildEntryText;
    }

    set
    {
        this.SetProperty<string>(ref this.buildEntryText, value);
        this.AddBuildCommand.RaiseCanExecuteChanged();
    }
}
4

2 回答 2

0

您的委托命令需要重新查询以检查命令是否可以执行。委托命令定义调用的事件CanExecuteChanged,该事件在 UI 线程上引发,以使每个调用控件重新查询以检查命令是否可以执行

这就是委托命令的样子(你的也可能类似)

public class DelegateCommand<T> : System.Windows.Input.ICommand
{
   private readonly Predicate<T> _canExecute;
   private readonly Action<T> _execute;

     public DelegateCommand(Action<T> execute)
    : this(execute, null)
     {
     }

    public DelegateCommand(Action<T> execute, Predicate<T> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        if (_canExecute == null)
            return true;

        return _canExecute((parameter == null) ? default(T) :(T)Convert.ChangeType(parameter, typeof(T)));
    }

    public void Execute(object parameter)
    {
        _execute((parameter == null) ? default(T) : (T)Convert.ChangeType(parameter, typeof(T)));
    }

    public event EventHandler CanExecuteChanged;
    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }
}

您正在将其绑定到TextBox

这是一个示例 ViewModel.cs

public class ViewModel
{
    private readonly DelegateCommand<string> MyButtonCommand;

    public ViewModel()
    {
        MyButtonCommand= new DelegateCommand<string>(
            (s) => { MessageBox.Show("Command Executed")}, //Execute
            (s) => { return !string.IsNullOrEmpty(_input); } //CanExecute
            );
    }

    public DelegateCommand<string> AddBuildCommand
    {
        get { return MyButtonCommand; }
    }

    private string _input;
    public string BuildEntryText
    {
        get { return _input; }
        set
        {
            _input = value;
            MyButtonCommand.RaiseCanExecuteChanged();
        }
    }
}  

并在您的XAML中

 <TextBox Text="{Binding BuildEntryText,   UpdateSourceTrigger=PropertyChanged}" />
<Button Command="{Binding AddBuildCommand}" Content="Add" />
于 2015-03-07T06:13:20.770 回答
0

我发现这是一个由两部分组成的问题,实际上并不是我的 DelegateCommand 的问题(至少,不完全是)。

1) 我需要按照 Rachel 的建议调用 RaiseCanExecuteChanged,否则 UI 不会刷新控件的 IsEnabled 属性。

2)我需要添加一个额外的条件来检查字符串的长度,而不是只检查它是否为空。显然,一个空的 TextBox 以 null 开头,但如果您添加字符然后删除它们,它不会再次返回为 null。 它是一个长度为 0 的字符串。

<TextBox Text="{Binding BuildEntryText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Command="{Binding AddBuildCommand}" Content="Add" />

public DelegateCommand AddBuildCommand { get; private set; }

this.AddBuildCommand = new DelegateCommand(() => this.AddBuild(), () => this.CanAddBuild());

public string BuildEntryText
{
    get
    {
        return this.buildEntryText;
    }

    set
    {
        this.SetProperty<string>(ref this.buildEntryText, value);

        // PART 1:
        this.AddBuildCommand.RaiseCanExecuteChanged();
    }
}

private bool CanAddBuild()
{
    // PART 2:
    if (this.BuildEntryText != null && this.BuildEntryText.Length > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}
于 2015-03-10T21:53:48.933 回答