【问题标题】:WPF Binding with Delay does not work properly带有延迟的 WPF 绑定无法正常工作
【发布时间】:2015-04-16 12:22:29
【问题描述】:

我正在尝试将延迟属性用于 WPF 绑定。下面的示例中有两个文本框绑定到同一个属性。第一个使用延迟属性,第二个不使用。

延迟效果很好。但是出乎意料的行为是,更改 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));
    }
}

【问题讨论】:

    标签: c# wpf binding


    【解决方案1】:

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

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

    不幸的是,该命令的“CanExecute”检查(RelayCommand 构造函数的第二个参数中的委托)也会在您输入数字时发生,并且Value1 尚未更改,因此按钮保持灰色,因为Value1 仍然等于初始值。一旦延迟过去并且Value1 发生更改,“CanExecute”就不会重新检查。

    您可以将CommandManager.InvalidateRequerySuggested(); 添加到您的Value1 设置器中,它应该可以工作:

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

    【讨论】:

      【解决方案2】:

      我建议你的 RelayCommand 是微软的默认实现。所以x =&gt; Value1 != InitialValue 就是Func&lt;bool&gt; _canExecute 条件。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多