13

コマンドがトリガーされる前またはトリガーされたときにバインディングを更新する方法はありますか? コマンドを使用して編集および保存できるテキスト フィールドがいくつかあり、キーボード ショートカットからアクセスできます。バインドは通常、テキスト フィールドがフォーカスを失ったときにのみ更新されるため、キーを押してデータを保存するときに、最後の変更は保持されません。代わりに、最初にテキスト フィールドからタブで移動して更新し、保存する必要があります。

エレガントな方法で更新を強制する方法はありますか? 私はMVVMを使用していますが(MVVMフレームワークは使用していません)、UI固有のものをコマンドコードから除外したいと思います。また、変更のたびにバインディングを更新するように変更したくはありません。フォーカスが失われた場合にのみバインディングを更新しても問題ありません。

4

7 に答える 7

11

フォーカスを変更するのではなく、現在の要素がTextBox. 他のコントロールでも同様のことができますが、私の経験では、この問題はTextBox.

  // if the current focused element is textbox then updates the source.     
    var focusedElement = Keyboard.FocusedElement as FrameworkElement;
    
    if (focusedElement is TextBox)
    {
       var expression = focusedElement.GetBindingExpression(TextBox.TextProperty);
        if (expression != null) expression.UpdateSource();
    }
于 2012-07-12T02:26:10.470 に答える
5

では、ソースがテキストボックス値で更新されるタイミングを定義するテキスト バインディングにTextBoxを設定する必要があります。UpdateSourceTriggerデフォルトでは、これはプロパティLostFocusTextであり、まさに何が起こっているかです。ソースがフォーカスを失ったときにのみソースを更新します。UpdateSourceTriggerの値を設定する必要がありPropertyChanged、テキスト ボックスの値が変更されるたびに更新されます。

例えば

<TextBox ... Text="{Binding Foo, UpdateSourceTrigger=PropertyChanged}"/>

Path は Binding コマンドを使用するときのデフォルト プロパティであるため、上記は次のようになります。Path=Foo

于 2016-01-15T19:53:42.283 に答える
2

値を要求する前に、フォーカスを他の要素に明示的に設定することで、これを解決しました。これは明らかに、現在フォーカスを持っている要素を失い、バインディングを更新します。

焦点を設定するために、他の質問に対する回答に触発されて、添付プロパティを作成しました。また、私の他の質問と一緒に、これを多少自動化しました。

したがって、それを使用するには、基本的にプロパティを要素 (この場合はタブ コントロール) にアタッチします。

<TabControl c:Util.ShouldFocus="{Binding ShouldClearFocus}">

私のビューモデルには、 を発生さShouldClearFocusせる標準プロパティである単純なブール値プロパティがあるPropertyChangedEventため、データバインディングが機能します。次に、フォーカスをリセットしたいときに設定ShouldClearFocusするだけです。true添付プロパティは自動的にフォーカスを設定し、プロパティ値を再度リセットします。ShouldClearFocusそうすれば、その間に設定する必要なく設定を続けることができますfalse

添付プロパティは、これを変更ハンドラーとして使用する標準実装です。

public static void ShouldFocusChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    if (!(bool)e.NewValue || !(obj is FrameworkElement))
        return;

    FrameworkElement element = (FrameworkElement)obj;
    if (element.Focusable)
        element.Focus();

    // reset value
    BindingExpression bindingExpression = BindingOperations.GetBindingExpression(obj, ShouldFocusProperty);
    if (bindingExpression != null)
    {
        PropertyInfo property = bindingExpression.DataItem.GetType().GetProperty(bindingExpression.ParentBinding.Path.Path);
        if (property != null)
            property.SetValue(bindingExpression.DataItem, false, null);
    }
    else
        SetShouldFocus(obj, false);
}
于 2012-06-27T14:07:37.177 に答える
0

UpdateSourceTrigger=PropertyChangedこれを行う最善の方法は、バインディングの を設定し、 を使用Reactive Extensionsしてイベント ストリームを調整することだと思います。この方法では、ユーザーが一定時間入力を停止した後にのみプロパティが更新されます (1/2 秒が適切な量です)。

プロパティは常に更新されるわけではありませんが、フォーカスを変更する必要なく更新されるため、これは素晴らしいことです。まさにあなたが望むもの。

Rx に関する非常に役立つ情報を次に示します。

バインド可能な IObservables hereを持つ MVVM 拡張ライブラリがあります。彼らがここに持っている例は、私が提案したことを正確に行っています。

あなたはエレガンスを求めました:ここにあります。そして、それほど多くの作業もありません。

于 2012-10-15T14:05:06.557 に答える
0

私は私のプロジェクトで以下を使用します。問題は、ボタンがフォーカスを受け取らなかったことです。

私のapp.xaml.csで

    EventManager.RegisterClassHandler(typeof(Button), ButtonBase.ClickEvent, new RoutedEventHandler(ButtonClick));

    private void ButtonClick(object sender, RoutedEventArgs e)
    {
        if (sender != null && sender is Button)
        {
            (sender as Button).Focus();
        }
    }
于 2012-06-19T06:42:23.520 に答える