TextBox Binding TwoWay не обновляется до тех пор, пока фокус не потеряет WP7

У меня есть страница с некоторыми текстовыми полями для ввода данных. Для привязки текстового поля установлено значение TwoWay. Данные в моей модели просмотра обновляются, только если текстовое поле теряет фокус. Если я нажимаю кнопку, например сохранение, а текстовое поле все еще имеет фокус, изменения в текстовом поле не изменяются в моей модели просмотра в событии сохранения.

Есть ли способ привязки сохранить значение текстового поля до того, как он потеряет фокус? Или мне нужно что-то сделать в событии сохранения?

Ответ 1

Вы можете использовать поведение UpdateTextBindingOnPropertyChanged из Prism Library для WP7, чтобы обновить связанное значение, когда текст изменяется вместо потерянного фокуса.

Ответ 2

Я предполагаю, что ваша кнопка "Сохранить" - это ApplicationBarButton (не обычная кнопка). Для обычных кнопок это будет просто работать, потому что они фокусируются, и, следовательно, привязка данных начнется.

Для ApplicationBarButtons на телефоне это немного отличается, потому что они не отвлекают внимание от клиентского приложения. Чтобы обеспечить принудительное связывание данных при нажатии кнопки "Сохранить", вы можете добавить в свой обработчик следующий код:

object focusObj = FocusManager.GetFocusedElement();
if (focusObj != null && focusObj is TextBox)
{
    var binding = (focusObj as TextBox).GetBindingExpression(TextBox.TextProperty);
    binding.UpdateSource();
}

Ответ 3

Скачать бесплатную книгу Чарльза Петцольда Программирование Windows Phone 7. На странице 387 он рассказывает о том, как это сделать.

В принципе, установите для свойства UpdateSourceTrigger значение Binding значение Explicit. Затем в обратном вызове TextBox TextChanged обновите источник привязки.

Ответ 4

Я иду в противоположном направлении @Praetorian.

Ваш TextBox имеет значение UpdateSourceTrigger по умолчанию LostFocus. Это означает, что значение только толкается в ваше свойство ViewModel, когда оно теряет фокус.

Вы можете установить UpdateSourceTrigger в PropertyChanged:

<TextBox UpdateSourceTrigger="PropertyChanged" Text="{Binding TextViewModelProperty}" />

Из http://msdn.microsoft.com/en-us/library/system.windows.data.binding.updatesourcetrigger.aspx:

Одно из значений UpdateSourceTrigger. По умолчанию используется значение по умолчанию, которое возвращает значение UpdateSourceTrigger по умолчанию свойства целевой цели. Однако значение по умолчанию для большинства свойства зависимостей PropertyChanged, а текст свойство имеет значение по умолчанию LostFocus.

Помните, это означает, что все, что является триггером обновления к этому свойству, будет происходить гораздо чаще (в основном с каждым нажатием клавиши, вместо одиночного "флеша", когда TextBox теряет фокус).

Надеюсь, что это поможет!

Ответ 5

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

UpdateBindingOnPropertyChangedBehviour.cs

using System;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Interactivity;

namespace MyCompany.MyProduct
{
    /// <summary>
    /// Custom behavior that updates the source of a binding on a text box as the text changes.
    /// </summary>
    public class UpdateTextBindingOnPropertyChanged : Behavior<TextBox>
    {
        /// <summary>
        /// Binding expression this behavior is attached to.
        /// </summary>
        private BindingExpression _expression;

        /// <summary>
        /// Called after the behavior is attached to an AssociatedObject.
        /// </summary>
        /// <remarks>
        /// Override this to hook up functionality to the AssociatedObject.
        /// </remarks>
        protected override void OnAttached()
        {
            base.OnAttached();

            // Hook events to change behavior
            _expression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
            AssociatedObject.TextChanged += OnTextChanged;
        }

        /// <summary>
        /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
        /// </summary>
        /// <remarks>
        /// Override this to unhook functionality from the AssociatedObject.
        /// </remarks>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            // Un-hook events
            AssociatedObject.TextChanged -= OnTextChanged;
            _expression = null;
        }

        /// <summary>
        /// Updates the source property when the text is changed.
        /// </summary>
        private void OnTextChanged(object sender, EventArgs args)
        {
            _expression.UpdateSource();
        }
    }
}

Это в основном очищенная версия кода Microsoft Prism 4.1 (см. проект Silverlight\Prism.Interactivity, если вы хотите просмотреть остальные).

Теперь, как его использовать:

  • Добавьте ссылку на сборку System.Windows.Interactivity на ваш проект в Windows Phone.
  • На каждой странице, где вы хотите использовать поведение, добавьте ссылку XAML на сборку: XMLNS: я = "CLR-имена: System.Windows.Interactivity; сборка = System.Windows.Interactivity"
  • Внутри XAML каждого TextBox, к которому вы хотите применить bahvior (у которого уже есть привязка TwoWay к вашему исходному свойству), добавьте следующее:

    < я: Interaction.Behaviors >
      < my: UpdateTextBindingOnPropertyChanged/" >
    </I: Interaction.Behaviors >

    Примечание: префикс "my:" может отличаться в вашем коде. Это просто ссылка пространства имен, в которой вы добавили класс поведения.

Ответ 6

попробуйте установить свойство UpdateSourceTrigger в свойство PropertyChanged

как это

Property="{Binding PropertyBinding, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"

Ответ 7

Я не пробовал @Praetorian ответ, так что если это хорошо работает, тогда сделайте это - в противном случае используйте события KeyUp и TextChanged для обновления источника привязки.