デフォルトのデータバインディングはオンTextBox
であり、フォーカスを失ったTwoWay
場合にのみテキストをプロパティにコミットします。TextBox
Enter? のキーを押したときにデータバインディングを行う簡単な XAML の方法はありTextBox
ますか。コードビハインドで行うのは非常に簡単ですが、これTextBox
が複雑なDataTemplate
.
これが私がこの問題を解決した方法です。コード ビハインドに入る特別なイベント ハンドラーを作成しました。
private void TextBox_KeyEnterUpdate(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
TextBox tBox = (TextBox)sender;
DependencyProperty prop = TextBox.TextProperty;
BindingExpression binding = BindingOperations.GetBindingExpression(tBox, prop);
if (binding != null) { binding.UpdateSource(); }
}
}
次に、これを XAML の KeyUp イベント ハンドラーとして追加しました。
<TextBox Text="{Binding TextValue1}" KeyUp="TextBox_KeyEnterUpdate" />
<TextBox Text="{Binding TextValue2}" KeyUp="TextBox_KeyEnterUpdate" />
イベント ハンドラーは、そのsender
参照を使用して、独自のバインディングを更新します。イベント ハンドラーは自己完結型であるため、複雑な DataTemplate で機能する必要があります。この 1 つのイベント ハンドラーを、この機能を必要とするすべてのテキスト ボックスに追加できるようになりました。
あなたが説明していることを行うための「純粋なXAML」の方法があるとは思いません。次のようにUpdateSourceTriggerプロパティを設定することで、TextBox 内のテキストが変更されるたびに (TextBox がフォーカスを失ったときではなく) 更新されるようにバインディングを設定できます。
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}" />
UpdateSourceTrigger を "Explicit" に設定し、TextBox の PreviewKeyDown イベントを処理して (Enter キーを探して)、目的を達成できますが、コード ビハインドが必要になります。おそらく、ある種の添付プロパティ (私のEnterKeyTraversalプロパティに似ています) が機能するでしょう。
TextBox から継承する独自のコントロールを簡単に作成し、プロジェクト全体で再利用できます。
これに似たものが機能するはずです:
public class SubmitTextBox : TextBox
{
public SubmitTextBox()
: base()
{
PreviewKeyDown += new KeyEventHandler(SubmitTextBox_PreviewKeyDown);
}
void SubmitTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
BindingExpression be = GetBindingExpression(TextBox.TextProperty);
if (be != null)
{
be.UpdateSource();
}
}
}
}
このステップを回避する方法があるかもしれませんが、それ以外の場合は、次のようにバインドする必要があります (Explicit を使用):
<custom:SubmitTextBox
Text="{Binding Path=BoundProperty, UpdateSourceTrigger=Explicit}" />
Ben と ausadmin の両方のソリューションを組み合わせると、非常に MVVM に適したソリューションになります。
<TextBox Text="{Binding Txt1, Mode=TwoWay, UpdateSourceTrigger=Explicit}">
<TextBox.InputBindings>
<KeyBinding Gesture="Enter"
Command="{Binding UpdateTextBoxBindingOnEnterCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}" />
</TextBox.InputBindings>
</TextBox>
...これは、TextBox
それ自体をパラメーターとしてに渡すことを意味しますCommand
。
これにより、次のようになります( VM で スタイルの実装Command
を使用している場合)。DelegateCommand
public bool CanExecuteUpdateTextBoxBindingOnEnterCommand(object parameter)
{
return true;
}
public void ExecuteUpdateTextBoxBindingOnEnterCommand(object parameter)
{
TextBox tBox = parameter as TextBox;
if (tBox != null)
{
DependencyProperty prop = TextBox.TextProperty;
BindingExpression binding = BindingOperations.GetBindingExpression(tBox, prop);
if (binding != null)
binding.UpdateSource();
}
}
このCommand
実装は、コード ビハインドのすべてのコードに使用できますが、これを独自のクラスに配置して、VM にTextBox
依存しないようにすることもできます。System.Windows.Controls
それは、コード ガイドラインがどれほど厳格であるかによって異なります。
これは、私には非常に簡単で、AttachedBehaviour を追加するよりも簡単に思えるアプローチです (これも有効なソリューションです)。デフォルトの UpdateSourceTrigger (TextBox の LostFocus) を使用し、コマンドにバインドされた Enter キーに InputBinding を追加します。
xamlは次のとおりです
<TextBox Grid.Row="0" Text="{Binding Txt1}" Height="30" Width="150">
<TextBox.InputBindings>
<KeyBinding Gesture="Enter"
Command="{Binding UpdateText1Command}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}},Path=Text}" />
</TextBox.InputBindings>
</TextBox>
次に、コマンド メソッドは次のとおりです。
Private Function CanExecuteUpdateText1(ByVal param As Object) As Boolean
Return True
End Function
Private Sub ExecuteUpdateText1(ByVal param As Object)
If TypeOf param Is String Then
Txt1 = CType(param, String)
End If
End Sub
TextBox はプロパティにバインドされています
Public Property Txt1 As String
Get
Return _txt1
End Get
Set(value As String)
_txt1 = value
OnPropertyChanged("Txt1")
End Set
End Property
これまでのところ、これはうまく機能しているようで、TextBox で Enter Key イベントをキャッチします。
TextBox で MultiBinding を使用している場合は、BindingOperations.GetMultiBindingExpression
の代わりにメソッドを使用する必要がありますBindingOperations.GetBindingExpression
。
// Get the correct binding expression based on type of binding
//(simple binding or multi binding.
BindingExpressionBase binding =
BindingOperations.GetBindingExpression(element, prop);
if (binding == null)
{
binding = BindingOperations.GetMultiBindingExpression(element, prop);
}
if (binding != null)
{
object value = element.GetValue(prop);
if (string.IsNullOrEmpty(value.ToString()) == true)
{
binding.UpdateTarget();
}
else
{
binding.UpdateSource();
}
}
ここでは、添付されたビヘイビアを使用して非常にエレガントに回答しました。
別の解決策(xamlを使用していませんが、それでもかなりきれいだと思います)。
class ReturnKeyTextBox : TextBox
{
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
if (e.Key == Key.Return)
GetBindingExpression(TextProperty).UpdateSource();
}
}