web-dev-qa-db-ja.com

TextBoxバインディングTwoWayは、フォーカスがWP7を失うまで更新されません

データ入力用のテキストボックスがいくつかあるページがあります。テキストボックスのバインドはTwoWayに設定されます。ビューモデルのデータは、テキストボックスがフォーカスを失った場合にのみ更新されます。保存などのボタンをクリックしても、テキストボックスにフォーカスがある場合、テキストボックスの変更は、保存イベントのビューモデルでは変更されません。

バインディングがフォーカスを失う前にテキストボックスの値を保存する方法はありますか?または、保存イベントで何かをする必要がありますか?

43
Josh Close

Prism Library for WP7UpdateTextBindingOnPropertyChanged動作を使用して、フォーカスが失われたときではなく、テキストが変更されたときにバインド値を更新できます。

8
Derek Lakin

保存ボタンは(通常のボタンではなく)ApplicationBarButtonであると思います。通常のボタンの場合、ボタンがフォーカスを取得し、データバインディングが機能するため、機能します。

電話のApplicationBarButtonsの場合、クライアントアプリからフォーカスを奪わないため、少し異なります。 [保存]ボタンをクリックしたときにデータバインディングが確実に開始されるように、ハンドラーに次のコードを追加できます。

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

Charles Petzoldの無料の本をダウンロード Programming Windows Phone 7 。 387ページで、彼はこれを行う方法について話します。

基本的に、UpdateSourceTriggerBindingプロパティをExplicitに設定します。次に、TextBoxTextChangedコールバックで、Bindingソースを更新します。

16
Praetorian

UpdateSourceTriggerプロパティを 'PropertyChanged'に設定してみてください

このような

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

@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値の1つ。デフォルトはDefaultで、ターゲットの依存関係プロパティのデフォルトのUpdateSourceTrigger値を返します。ただし、ほとんどの依存関係プロパティのデフォルト値はPropertyChangedですが、Textプロパティのデフォルト値はLostFocusです。

これは、このプロパティの更新によってトリガーされるすべてのことがはるかに頻繁に発生することを覚えておいてください(基本的に、TextBoxがフォーカスを失ったときに1回の「フラッシュ」ではなく、キーを押すたびに)。

お役に立てば幸いです。

7
rrhartjr

これが、Derekが提案した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プロジェクトを参照してください)。

それを使用する方法:

  1. System.Windows.Interactivity Assemblyへの参照をWindows Phoneプロジェクトに追加します。
  2. 動作を使用する各ページで、アセンブリへのXAML参照を追加します:xmlns:i = "clr-namespace:System.Windows.Interactivity; Assembly = System.Windows.Interactivity"
  3. Bahviorを適用する各TextBoxのXAML内(既にソースプロパティへのTwoWayバインディングを持っています)に、次を追加します。

    <i:Interaction.Behaviors>
    <my:UpdateTextBindingOnPropertyChanged />
    </ i:Interaction.Behaviors>

    注: "my:"プレフィックスはコードによって異なる場合があります。これは、動作クラスを追加した名前空間参照です。

6
Tony Wall

私は@Praetorianの回答を試していないので、うまくいく場合はそれを行います。そうでない場合は、KeyUpイベントとTextChangedイベントの両方を使用してBindingソースを更新します。

1
PhilChuang

このリンクには、WinRTで完全に機能するソリューションがあります。彼はTextBoxを継承し、新しいプロパティBindableTextを追加します。

http://www.familie-smits.com/post/2012/07/29/UpdateSourceTrigger-in-WinRT.aspx

0
jlo