Привязка данных не обновляет свойство при нажатии Enter в диалоговом окне с кнопкой по умолчанию - PullRequest
9 голосов
/ 09 сентября 2011

Мои настройки описаны ниже:

  • Приложение WPF 4
  • MVVM Lite Framework
  • В главном окне в диалоговом режиме отображается окно «Добавить элемент» (с помощью view.ShowDialog ();)
  • Диалог имеет несколько полей ввода и кнопку «Сохранить», для которой свойство IsDefault имеет значение True
  • Кнопка «Сохранить» обрабатывается с помощью привязки к команде
  • Привязка данных определяется между полями ввода в XAML представления и соответствующими свойствами в ViewModel (один из способов, чтобы пользовательский интерфейс мог обновить ViewModel, с Mode = OneWayToSource)

Проблема в том, что когда я нажимаю Enter на клавиатуре, значение, которое я указал в последнем поле ввода, не помещается в базовое свойство ViewModel.

Я подозреваю, что это как-то связано с тем, что поле ввода не потеряло фокус перед закрытием окна (и, таким образом, все привязки "распались"). Для сравнения, если я нажимаю кнопку «Сохранить» (вместо того, чтобы обрабатывать ее щелчок в окне при вводе), значение равно , обновляется в свойстве. Более того, если я добавлю (ужас! Ужас!) Обработчик события к событию Click кнопки и вызову button.Focus () в коде позади, все будет работать!

Что может быть лекарством?

Я, очевидно, не хочу обрабатывать какие-либо события закрытия окна и "вручную" извлекать пропущенные значения ... Это нарушило бы всю концепцию MVVM: - (

Есть лучшие предложения?

Спасибо, Alex

Ответы [ 4 ]

13 голосов
/ 10 сентября 2011

По умолчанию TextBox только уведомляет свой источник об изменении значения после потери фокуса.Вы можете изменить это в привязке, установив UpdateSourceTrigger=PropertyChanged.Это заставит TextBox отправлять уведомление об обновлении своему источнику, текст которого изменяется, а не только тогда, когда он теряет фокус.

Если вы не хотите отправлять уведомление об обновлении при каждом нажатии клавиши, вы можете создать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
3 голосов
/ 10 сентября 2011

Попробуйте это.

{Свойство привязки, UpdateSourceTrigger = PropertyChanged, Mode = OneWayToSource}

0 голосов
/ 17 июля 2017

Простой трюк заключается в перемещении фокуса от элемента управления, например, к самой кнопке.Вы можете сделать это в обработчике нажатия кнопки, так как он будет выполнен перед командой привязки:

    public MyView()
    {
        InitializeComponent();

        _button.Click += delegate
        {
            _button.Focus();
        };
    }

Если вам не нравится код позади в вашем представлении, вы также можете сделать это вповедение, которое вы добавляете к своей кнопке.

0 голосов
/ 17 января 2013

Это просто ошибка WPF. (Дизайн или реализация, я не знаю.) Обновление TextBox при потере фокуса является ожидаемым поведением в большинстве случаев, и кнопка по умолчанию должна работать в диалоговых окнах.

В качестве обходного пути, я думаю, что это неправильное направление для уравновешивания с TextBox. Лучшее решение состоит в том, чтобы заставить фокус на кнопку по умолчанию.

...