WPF 延迟绑定无法正常工作

WPF Binding with Delay does not work properly

我正在尝试将 Delay-属性 用于 WPF 绑定。在以下示例中,两个文本框绑定到同一个 属性。第一个使用 Delay-属性,第二个不使用。

延迟效果很好。但意外的行为是,更改 TextBox1 中的值不会立即启用 Button,但 TextBox2 会。单击鼠标、回车键或使用 Tab 键离开文本框可启用该按钮。

有人知道我该如何解决这个问题或原因是什么吗?

查看:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <TextBox x:Name="TextBox1" Text="{Binding Value1, UpdateSourceTrigger=PropertyChanged, Delay=1000}"/>
    <TextBox x:Name="TextBox2" Text="{Binding Value1, UpdateSourceTrigger=PropertyChanged}"/>
        <Button Command="{Binding ButtonCommand}" Content="GO!"></Button>
</StackPanel>

代码隐藏:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private const decimal InitialValue = 400;

    private decimal _value1;
    public decimal Value1
    {
        get { return _value1; }
        set
        {
            _value1 = value; 
            OnPropertyChanged();                
        }
    }

    public ICommand ButtonCommand { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        Value1 = InitialValue;
        ButtonCommand = new RelayCommand(x => { /*Do something*/ }, x => Value1 != InitialValue);
        DataContext = this;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

我建议你的RelayCommand是微软的默认实现。所以 x => Value1 != InitialValueFunc<bool> _canExecute 条件。

您可能需要在 _canExecute 条件更改后引发 RelayCommandRaiseCanExecuteChanged 事件。它不酷,但我认为应该可以。

问题是 WPF 命令系统 "CanExecute" 检查是由 Control 事件触发的,而不是由 ViewModel 中的更改触发的。

所以发生的事情是你输入一个数字,触发一个事件。绑定触发响应,但由于延迟,它不会立即更新 ViewModel 属性。

不幸的是,命令的 "CanExecute" 检查(RelayCommand 构造函数的第二个参数中的委托)也会响应您输入的数字而发生,并且 Value1 没有' 尚未更改,因此按钮保持灰色,因为 Value1 仍等于初始值。一旦延迟过去并且 Value1 发生变化,将不会重新检查 "CanExecute"。

您可以将 CommandManager.InvalidateRequerySuggested(); 添加到您的 Value1 setter 并且它应该有效:

    set
    {
        _value1 = value; 
         OnPropertyChanged();                              
         CommandManager.InvalidateRequerySuggested();           
    }