Принять несоответствие кнопки и привязки данных

Удобно иметь кнопку «Принять» (в WPF: IsDefault = «True») в форме.

В мире Windows Forms я использовал для чтения данных из пользовательского интерфейса объект(ы) в соответствующем событии Click кнопки.

Но с WPF следует использовать привязку данных. В конструкторе окна я установил this.DataContext = test;

И тут возникает проблема: пользователь ввел какой-то текст в TextBox2 и нажал клавишу Enter. Теперь команда, привязанная к кнопке ОК, выполняется, данные сохраняются.

Но это не правильные данные! Почему? TextBox2 еще не потерял фокус, и, следовательно, ViewModel еще не обновился. Изменение UpdateSourceTrigger на PropertyChanged не всегда уместно (например, отформатированные числа), я ищу общее решение.

Как вы преодолеваете такую ​​проблему?


person Bernhard Hiller    schedule 05.07.2012    source источник
comment
Возможно, вы можете явно обновить данные с помощью TextBox2.GetBindingExpression(TextProperty).UpdateSource(); в обработчике событий закрытия.   -  person LPL    schedule 07.07.2012


Ответы (1)


Обычно я использую настраиваемое вложенное свойство, чтобы сообщить 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();
            }
        }
    }
}
person Rachel    schedule 05.07.2012