1

在表单上有一个“接受按钮”(在 WPF 中:IsDefault="True")很方便。

在 Windows 窗体世界中,我曾经在按钮的相应 Click 事件中将数据从 UI 读取到对象。

但是对于 WPF,应该使用数据绑定。在Window的构造函数中,我设置了this.DataContext = test;

问题来了:用户在 TextBox2 中输入了一些文本,然后按了 Enter 键。现在,绑定到 OK 按钮的命令被执行,数据被保存。

但这不是正确的数据!为什么?TextBox2 尚未失去焦点,因此 ViewModel 尚未更新。将 UpdateSourceTrigger 更改为 PropertyChanged 并不总是合适的(例如格式化数字),我正在寻找一个通用的解决方案。

你如何克服这样的问题?

4

1 回答 1

0

通常我使用自定义附加属性来告诉 WPF 在按下 Enter 键时更新绑定源

它在 XAML 中使用如下:

<TextBox Text="{Binding SomeProperty}" 
         local:TextBoxProperties.EnterUpdatesTextSource="True" />

附加属性的代码如下:

public class TextBoxProperties
{
    // When set to True, Enter Key will update Source
    public static readonly DependencyProperty EnterUpdatesTextSourceProperty =
        DependencyProperty.RegisterAttached("EnterUpdatesTextSource", typeof(bool),
                                            typeof(TextBoxProperties),
                                            new PropertyMetadata(false, EnterUpdatesTextSourcePropertyChanged));

    // Get
    public static bool GetEnterUpdatesTextSource(DependencyObject obj)
    {
        return (bool)obj.GetValue(EnterUpdatesTextSourceProperty);
    }

    // Set
    public static void SetEnterUpdatesTextSource(DependencyObject obj, bool value)
    {
        obj.SetValue(EnterUpdatesTextSourceProperty, value);
    }

    // Changed Event - Attach PreviewKeyDown handler
    private static void EnterUpdatesTextSourcePropertyChanged(DependencyObject obj,
                                                              DependencyPropertyChangedEventArgs e)
    {
        var sender = obj as UIElement;
        if (obj != null)
        {
            if ((bool)e.NewValue)
            {
                sender.PreviewKeyDown += OnPreviewKeyDownUpdateSourceIfEnter;
            }
            else
            {
                sender.PreviewKeyDown -= OnPreviewKeyDownUpdateSourceIfEnter;
            }
        }
    }

    // If key being pressed is the Enter key, and EnterUpdatesTextSource is set to true, then update source for Text property
    private static void OnPreviewKeyDownUpdateSourceIfEnter(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            if (GetEnterUpdatesTextSource((DependencyObject)sender))
            {
                var obj = sender as UIElement;
                BindingExpression textBinding = BindingOperations.GetBindingExpression(
                    obj, TextBox.TextProperty);

                if (textBinding != null)
                    textBinding.UpdateSource();
            }
        }
    }
}
于 2012-07-05T13:01:03.297 回答