在具有默认按钮的对话框上按Enter键时,数据绑定不会更新属性

Ale*_*lex 9 data-binding wpf mvvm

我的设置如下所述:

  • WPF 4申请
  • MVVM Lite框架
  • 在对话框模式下,主窗口顶部显示"添加项目"窗口(使用view.ShowDialog();)
  • 该对话框有许多输入字段,以及将其IsDefault属性设置为True的"保存"按钮
  • 使用绑定到Command来处理"保存"按钮
  • 数据绑定在视图的XAML中的输入字段和ViewModel中的相应属性之间定义(一种方式,UI用于更新ViewModel,Mode = OneWayToSource)

问题是,当我按下键盘上的Enter键时,我在最后一个输入字段中提供的值不会被推送到ViewModel的底层属性.

我怀疑这与在窗口关闭之前输入字段没有丢失焦点这一事实有关(因此所有绑定都"解散").为了进行比较,如果我单击 "保存"按钮(而不是让Enter上的窗口处理其Click),则会在属性中更新该值.此外,如果我为按钮的Click事件添加(恐怖!恐怖!)事件处理程序,并在代码隐藏中调用button.Focus(),一切正常!

什么可以补救?

我显然不想处理任何窗口关闭事件,并"手动"获取缺少值...这将违反整个MVVM概念:-(

有更好的建议吗?

谢谢,Alex

Rac*_*hel 14

默认情况下,TextBox只有在失去焦点时,才会通知其来源其值已更改.您可以通过设置更改绑定中的内容UpdateSourceTrigger=PropertyChanged.这将使TextBox向其源发送更新通知,其Text将被更改,而不是仅在它失去焦点时.

如果您不想在按下任何键时发送更新通知,则可以创建一个AttachedProperty更新源,如果按下Enter键.

这是我用于这种情况的AttachedProperty:

// When set to True, Enter Key will update Source
#region EnterUpdatesTextSource DependencyProperty

// Property to determine if the Enter key should update the source. Default is False
public static readonly DependencyProperty EnterUpdatesTextSourceProperty =
    DependencyProperty.RegisterAttached("EnterUpdatesTextSource", typeof (bool),
                                        typeof (TextBoxHelper),
                                        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();
        }
    }
}

#endregion //EnterUpdatesTextSource DependencyProperty
Run Code Online (Sandbox Code Playgroud)

  • 要使用上面的附加属性,您需要将其放入一个静态类中(例如`public class static EnterUpdatesTextSourceBehaviour`)。然后在 XAML 中,您想在开头添加对包含此类的程序集的引用(例如 `xmlns:myHelpers="clr-namespace:MyHelpers`),然后在 `<TextBox>` 元素中添加附加属性设置为 true(例如`<TextBox myHelpers:EnterUpdatesTextSourceBehaviour.EnterUpdatesTextSource="True">`) (2认同)