【问题标题】:Why isn't my textbox updating the CanExecute value for my WPF button command?为什么我的文本框没有更新我的 WPF 按钮命令的 CanExecute 值?
【发布时间】:2019-12-07 16:27:05
【问题描述】:

我正在尝试通过实现一个简单的按钮和文本框来学习 WPF。我想了解为什么我的按钮 IsEnabled 状态没有根据我的文本字段的值进行更新。

XAML:

<TextBox Height="100" 
         TextWrapping="Wrap" 
         Text="{Binding Test,NotifyOnSourceUpdated=True,NotifyOnTargetUpdated=True}" 
         VerticalAlignment="Top" 
         Padding="5, 3, 1, 1"
         AcceptsReturn="True" Margin="161,10,10,0"/>

<Button Content="Go" 
         IsEnabled="{Binding MyButtonCanExecute}"
         Command="{Binding MyButtomCommand}"
         HorizontalAlignment="Left" 
         Margin="64,158,0,0" 
         VerticalAlignment="Top" Width="75"/>

C#:

class MainWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public bool MyButtonCanExecute
    {
        get
        {
            return !String.IsNullOrWhiteSpace(Test);
        }
    }

    private ICommand myButtonCommand;
    public ICommand MyButtomCommand
    {
        get
        {
            if(myButtonCommand == null)
            {
                myButtonCommand = new RelayCommand(ShowMessage, param => this.MyButtonCanExecute);
            }
            return myButtonCommand;
        }
    }

    private string test;
    public string Test
    {
        get { return this.test; }
        set
        {
            if (this.test != value)
            {
                this.test = value;
                this.NotifyPropertyChanged("Test");
            }
        }
    }

    public MainWindowViewModel()
    {
        //
    }

    public void ShowMessage(object obj)
    {
        MessageBox.Show("Value of textbox is set to: " + this.Test);
    }

    public void NotifyPropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

问题:

  1. 当我在文本框中键入时,Test 设置器中的断点没有被命中。为什么?如果文本框绑定到Test 属性,这不是重点吗?

  2. 当我在文本框中输入时,MyButtonCanExecute 会不断被调用。但是,在调试中test 的值始终为空……为什么?我在文本框中输入的内容不应该是什么吗?

主要问题似乎是Test 的值不会在我输入时更新。

我知道将IsEnabled 状态绑定到test 的长度可能有不同的方法,但我想了解我对 WPF 工作原理的理解有什么问题。

【问题讨论】:

  • “当我在文本框中键入时,我在测试设置器中的断点没有被命中”文本框不会立即更新 Text 属性的绑定,除非您设置 UpdateSourcetrigger=PropertyChanged - 默认情况下它是 LostFocus .单击按钮并调用 setter(假设 Window.DataContext 设置正确)
  • @ASh 谢谢,它现在在测试设置器中获得了价值。我在按钮的 IsEnabled 中添加了相同的 UpdateSourceTrigger,但输入后仍然无法启用?编辑:没关系,我自己修好了。将在下面添加答案并提及您。
  • IsEnabled 绑定到 MyButtonCanExecute,它不会在更改时通知。 this.NotifyPropertyChanged("Test"); this.NotifyPropertyChanged("MyButtonCanExecute"); - 这将是解决这个问题。但是:通常你不绑定 IsEnabled。 IsEabled 是基于绑定命令的 CanExecute() 设置的 - ICommand 有一个事件来通知何时应该重新评估 CanExecute(以及下一个 IsEnabled)
  • 是的,谢谢,设法弄清楚这一点。我已经发布了一个答案,以防其他人将来遇到同样的问题。感谢您的帮助。

标签: c# wpf mvvm binding


【解决方案1】:

为未来的读者回答我自己的问题。感谢 @ASh 为我指明了正确的方向。

问题是,在输入文本框时,UpdateSourceTrigger 有它的默认值(因为我没有在 XAML 中设置它)。这意味着文本框绑定的属性在元素失去焦点之前不会更新,而不是在其文本更改时。

解决办法:

将文本框的文本字段更改为:

 Text="{Binding Test,UpdateSourceTrigger=PropertyChanged}" 

注意,新的UpdateSourceTrigger=PropertyChanged 表示每次输入时源属性 (MainWindowViewModel.Test) 都会更新。

然后,在 Test 属性设置中,我必须为 MyButtonCanExecute 属性添加一个新的 NotifyPropertyChanged 调用,该调用取决于 Test 的值:

    private string test;
    public string Test
    {
        get { return this.test; }
        set
        {
            if (this.test != value)
            {
                this.test = value;
                this.NotifyPropertyChanged("Test");
                this.NotifyPropertyChanged("MyButtonCanExecute");
            }
        }
    }

还将UpdateSourceTrigger 添加到按钮的IsEnabled 值中:

 <Button Content="Go" 
      IsEnabled="{Binding MyButtonCanExecute,UpdateSourceTrigger=PropertyChanged}"
      Command="{Binding MyButtomCommand}" />

编辑: 更好的解决方案是完全删除 IsEnabled 绑定,这样您就可以:

 <Button Content="Go" 
      Command="{Binding MyButtomCommand}" />

这是因为当我们创建MyButtonCommand 时,我们将MyButtonCanExecute 作为CanExecute 属性传递给RelayCommand

 myButtonCommand = new RelayCommand(ShowMessage, param => this.MyButtonCanExecute);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-13
    • 1970-01-01
    • 2021-03-12
    • 2010-10-09
    • 2021-04-06
    相关资源
    最近更新 更多