c# - WPF:如果 TextBox 中的文本发生更改,则更新按钮

标签 c# wpf icommand

为了学习 WPF CommandCommandParameter,我有一个小型 WPF 应用程序,其中包含一个 TextBox 和一个 Button。每当按下按钮时,都应调用 ICommandTest,并将文本框的文本作为参数。

这很好用。下一步是:如果文本变得太小,则应禁用该按钮。

我使用MVVMLight来实现该命令。下面的代码足以在按下按钮时调用方法 Test。

到目前为止的代码

以下工作原理:启动时,文本框获得正确的初始文本。该按钮询问 View 模型此文本是否可以用作测试参数:

public class MyViewModel
{
    public ICommand CommandTest {get;}

    public MyViewModel()
    {
        this.CommandTest = new RelayCommand<string>(this.Test, this.CanTest); 
    }

    private bool CanTest(string text)
    {
        // text should have a minimum length of 4
        return text != null && text.Length >= 4;
    }
    private void Test(string text)
    {
        //...
    }

    // ...

}

XAML:水平 StackPanel 中的可编辑文本框和按钮。

<StackPanel Name="Test" Orientation="Horizontal" Background="AliceBlue">
    <TextBox Name="ProposedTestValue"
             Text="Alle eendjes zwemmen in het water"
             Width="500" Height="20"/>

    <Button x:Name="ButtonTest" Content="Change"
                    Height="auto" Width="74"
                    Padding="5,2"
                    Command="{Binding Path=CommandTest}"
                    CommandParameter="{Binding ElementName=ProposedTestValue, Path=Text}"/>
</StackPanel>

文本更改

如果我更改文本并按下按钮,则会使用更改后的文本调用该命令。所以 CommandCommandParameter 可以工作。

但是,如果文本小于 4 个字符,该按钮不会禁用。。每次按钮绑定(bind)的CommandParameter值发生变化时,按钮都应该询问其命令是否可以执行。

如何做到这一点?

NotifyOnSourceUpdated

Yosef Bernal 建议添加 NotifyOnSourceUpdated:

<Button x:Name="ButtonChangeTestText" Content="Change"
                Height="30" Width="74" Padding="5,2"
                Command="{Binding Path=CommandTest}"
                CommandParameter="{Binding ElementName=ProposedTestTextValue,
                    Path=Text, NotifyOnSourceUpdated=True}"/>

唉,这并没有改变任何东西:在启动时,使用正确的参数调用初始 CanTest。更改文本不会导致 CanTest。如果我按下按钮 CanTest 将使用正确的值进行调用。如果文本很小,CanTest 返回 false,因此不执行该命令。但是,即使 CanExecute 返回 false,该按钮仍保持启用状态。

如果不能执行,我应该告诉按钮做什么吗?或者禁用该按钮是默认行为吗?

最佳答案

您可以将 TextBoxText 属性绑定(bind)到 MyViewModel 上的 Text 属性。

<TextBox Name="ProposedTestValue" Text="{Binding Text}" Width="500" Height="20"/>

MyViewModel 中使用支持字段 _text 创建相应的 Text 属性。

private string _text;

public string Text
{
   get => _text;
   set
   {
      if (_text != value)
      {
         _text = value;
         CommandTest.RaiseCanExecuteChanged();
      }
   }
}

只要更新 Text 属性,RaiseCanExecuteChanged 方法就会强制重新评估 CanExecute,这取决于您的 UpdateSourceTrigger 。您不再需要 CommandParameter,因为您可以在 View 模型中使用 Text 属性。

public MyViewModel()
{
   this.CommandTest = new RelayCommand(this.Test, this.CanTest); 
}

private bool CanTest()
{
   return Text != null && Text.Length >= 4;
}

private void Test()
{
   // ...use "Text" here.
}

注意:如果您打算更新 View 模型中的 Text 属性,则必须实现 INotifyPropertyChanged,否则更改后的值将不会反射(reflect)在 View 中。

关于c# - WPF:如果 TextBox 中的文本发生更改,则更新按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63174956/

相关文章:

c# - 如何区分一个 RabbitMQ 队列中的两个 JSON 对象?

wpf - 将输入解释为选项卡 WPF

c# - 向 WPF ComboBox 控件添加标签的简单方法

WPF ContextMenu Dictionary<Key, List<Value>> 数据绑定(bind)

c# - LINQ 何时执行更新的数据列表?

C# Gridview 第一行数据不返回

wpf - 带导航的ICommand

c# - 如何从 xamarin 表单中的绑定(bind)命令调用函数

c# - WPF - 知道哪个控件最终会获得焦点

c# - 如何更改文件扩展名的默认图标?