Prism MVVM Ключи доступа UpdateSourceTrigger =»LostFocus» — Это не позволяет мне сохранять обновленное текстовое поле без предварительной потери фокуса

#c# #mvvm #prism #propertychanged #access-keys

#c# #mvvm #prism #propertychanged #ключи доступа

Вопрос:

Не совсем уверен, как решить эту проблему:

У меня есть кнопка «Сохранить», к которой прикреплены ключи доступа … но, если я ввожу что-то в текстовое поле и нажимаю клавиши доступа для сохранения, текстовое поле не обновляет мою viewmodel, потому что оно никогда не теряло фокус. Есть ли способ решить эту проблему, помимо изменения UpdateSourceTrigger на PropertyChanged?

Комментарии:

1. Почему вы не можете изменить триггер на PropertyChanged?

2. Это потребовало бы, чтобы ВСЕ свойства делали это, и это приводит к множеству уведомлений, которые кажутся ненужными… Кроме того, что, если кто-то захочет отменить свои изменения…

Ответ №1:

Ваша проблема заключается в UpdateSourceTrigger="LostFocus"

Это значение используется по умолчанию для текстовых полей и означает, что текстовое поле обновит свое привязанное значение только тогда, когда оно потеряет фокус

Один из способов принудительно обновить его без настройки UpdateSourceTrigger="PropertyChanged" — подключиться к событию нажатия клавиши, и если комбинация клавиш вызывает сохранение, сначала вызовите UpdateSource()

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

Он используется следующим образом:

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

и прикрепленное определение свойства выглядит следующим образом:

 public class TextBoxProperties
{
    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  = OnPreviewKeyDown_UpdateSourceIfEnter;
            }
            else
            {
                sender.PreviewKeyDown -= OnPreviewKeyDown_UpdateSourceIfEnter;
            }
        }
    }

    // If key being pressed is the Enter key, and EnterUpdatesTextSource is set to true, then update source for Text property
    private static void OnPreviewKeyDown_UpdateSourceIfEnter(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();
            }
        }
    }
}
  

Комментарии:

1. Хороший трюк, но недостатком является то, что его сложнее использовать, чем изменение моих элементов управления для сохранения с помощью PropertyChanged вместо LostFocus. Думаю, я просто хотел бы, чтобы Microsoft выполнила LostFocus при выполнении ключа доступа. В принципе, выполнение ключа доступа должно было быть таким же, как фактическое использование мыши для нажатия на кнопку. Хотя мне нравится этот трюк … вздох