C# 按下 Enter 键时绑定 TextBox
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/563195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bind TextBox on Enter-key press
提问by Jobi Joy
The default databinding on TextBox
is TwoWay
and it commits the text to the property only when TextBox
lost its focus.
默认的数据绑定TextBox
是TwoWay
,只有在TextBox
失去焦点时才将文本提交给属性。
Is there any easy XAML way to make the databinding happen when I press the Enterkey on the TextBox
?. I know it is pretty easy to do in the code behind, but imagine if this TextBox
is inside some complex DataTemplate
.
当我按下?Enter上的键时,是否有任何简单的 XAML 方法可以使数据绑定发生TextBox
。我知道在后面的代码中很容易做到,但想象一下,如果这TextBox
是在一些复杂的DataTemplate
.
采纳答案by Samuel Hyman
You can make yourself a pure XAML approach by creating an attached behaviour.
您可以通过创建附加行为使自己成为纯 XAML 方法。
Something like this:
像这样的东西:
public static class InputBindingsManager
{
public static readonly DependencyProperty UpdatePropertySourceWhenEnterPressedProperty = DependencyProperty.RegisterAttached(
"UpdatePropertySourceWhenEnterPressed", typeof(DependencyProperty), typeof(InputBindingsManager), new PropertyMetadata(null, OnUpdatePropertySourceWhenEnterPressedPropertyChanged));
static InputBindingsManager()
{
}
public static void SetUpdatePropertySourceWhenEnterPressed(DependencyObject dp, DependencyProperty value)
{
dp.SetValue(UpdatePropertySourceWhenEnterPressedProperty, value);
}
public static DependencyProperty GetUpdatePropertySourceWhenEnterPressed(DependencyObject dp)
{
return (DependencyProperty)dp.GetValue(UpdatePropertySourceWhenEnterPressedProperty);
}
private static void OnUpdatePropertySourceWhenEnterPressedPropertyChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
UIElement element = dp as UIElement;
if (element == null)
{
return;
}
if (e.OldValue != null)
{
element.PreviewKeyDown -= HandlePreviewKeyDown;
}
if (e.NewValue != null)
{
element.PreviewKeyDown += new KeyEventHandler(HandlePreviewKeyDown);
}
}
static void HandlePreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
DoUpdateSource(e.Source);
}
}
static void DoUpdateSource(object source)
{
DependencyProperty property =
GetUpdatePropertySourceWhenEnterPressed(source as DependencyObject);
if (property == null)
{
return;
}
UIElement elt = source as UIElement;
if (elt == null)
{
return;
}
BindingExpression binding = BindingOperations.GetBindingExpression(elt, property);
if (binding != null)
{
binding.UpdateSource();
}
}
}
Then in your XAML you set the InputBindingsManager.UpdatePropertySourceWhenEnterPressedProperty
property to the one you want updating when the Enterkey is pressed. Like this
然后在您的 XAML 中,您将InputBindingsManager.UpdatePropertySourceWhenEnterPressedProperty
属性设置Enter为按下键时要更新的属性。像这样
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}"
b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text"/>
(You just need to make sure to include an xmlns clr-namespace reference for "b" in the root element of your XAML file pointing to which ever namespace you put the InputBindingsManager in).
(您只需要确保在 XAML 文件的根元素中包含“b”的 xmlns clr-namespace 引用,指向您将 InputBindingsManager 放入的命名空间)。
回答by Matt Hamilton
I don't believe that there's any "pure XAML" way to do what you're describing. You can set up a binding so that it updates whenever the text in a TextBox changes (rather than when the TextBox loses focus) by setting the UpdateSourceTriggerproperty, like this:
我不相信有任何“纯 XAML”的方式来做你所描述的事情。您可以通过设置UpdateSourceTrigger属性来设置绑定,以便它在 TextBox 中的文本发生更改时(而不是在 TextBox 失去焦点时)更新,如下所示:
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}" />
If you set UpdateSourceTrigger to "Explicit" and then handled the TextBox's PreviewKeyDown event (looking for the Enter key) then you could achieve what you want, but it would require code-behind. Perhaps some sort of attached property (similar to my EnterKeyTraversalproperty) woudld work for you.
如果您将 UpdateSourceTrigger 设置为“Explicit”,然后处理 TextBox 的 PreviewKeyDown 事件(寻找 Enter 键),那么您可以实现您想要的,但它需要代码隐藏。也许某种附加属性(类似于我的EnterKeyTraversal属性)将为您工作。
回答by Ryan Versaw
You could easily create your own control inheriting from TextBox and reuse it throughout your project.
您可以轻松地创建自己的继承自 TextBox 的控件并在整个项目中重复使用它。
Something similar to this should work:
类似的东西应该可以工作:
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();
}
}
}
}
There may be a way to get around this step, but otherwise you should bind like this (using Explicit):
可能有办法绕过这一步,但否则你应该像这样绑定(使用显式):
<custom:SubmitTextBox
Text="{Binding Path=BoundProperty, UpdateSourceTrigger=Explicit}" />
回答by akjoshi
In case you are using MultiBinding with your TextBox you need to use BindingOperations.GetMultiBindingExpression
method instead of BindingOperations.GetBindingExpression
.
如果您在 TextBox 中使用 MultiBinding,则需要使用BindingOperations.GetMultiBindingExpression
method 而不是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();
}
}
回答by Ben
This is how I solved this problem. I created a special event handler that went into the code behind:
这就是我解决这个问题的方法。我创建了一个特殊的事件处理程序,它进入了后面的代码:
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(); }
}
}
Then I just added this as a KeyUp event handler in the XAML:
然后我只是将它添加为 XAML 中的 KeyUp 事件处理程序:
<TextBox Text="{Binding TextValue1}" KeyUp="TextBox_KeyEnterUpdate" />
<TextBox Text="{Binding TextValue2}" KeyUp="TextBox_KeyEnterUpdate" />
The event handler uses its sender
reference to cause it's own binding to get updated. Since the event handler is self-contained then it should work in a complex DataTemplate. This one event handler can now be added to all the textboxes that need this feature.
事件处理程序使用它的sender
引用来更新它自己的绑定。由于事件处理程序是自包含的,因此它应该在复杂的 DataTemplate 中工作。现在可以将这个事件处理程序添加到需要此功能的所有文本框。
回答by ausadmin
Here is an approach that to me seems quite straightforward, and easier that adding an AttachedBehaviour (which is also a valid solution). We use the default UpdateSourceTrigger (LostFocus for TextBox), and then add an InputBinding to the Enter Key, bound to a command.
这是一种对我来说似乎很简单的方法,并且比添加 AttachedBehaviour(这也是一个有效的解决方案)更容易。我们使用默认的UpdateSourceTrigger(LostFocus for TextBox),然后在回车键上添加一个InputBinding,绑定到一个命令。
The xaml is as follows
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>
Then the Command methods are
然后命令方法是
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
And the TextBox is bound to the Property
并且 TextBox 绑定到属性
Public Property Txt1 As String
Get
Return _txt1
End Get
Set(value As String)
_txt1 = value
OnPropertyChanged("Txt1")
End Set
End Property
So far this seems to work well and catches the Enter Key event in the TextBox.
到目前为止,这似乎运行良好,并在 TextBox 中捕获了 Enter Key 事件。
回答by Mr.Pidra
More simple, just set UpdateSourceTrigger
to PropertyChanged
in your TextBox
's binding without adding anything in codebehind.
Just like this:
更简单,只需在您的绑定中设置UpdateSourceTrigger
为PropertyChanged
,TextBox
而无需在代码隐藏中添加任何内容。像这样:
<TextBox Text="{Binding Path=BoundProperty, UpdateSourceTrigger=PropertyChanged}"/>
It works for me.
这个对我有用。
回答by toadflakz
If you combine both Ben and ausadmin's solutions, you end up with a very MVVM friendly solution:
如果你结合 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>
...which means you are passing the TextBox
itself as the parameter to the Command
.
...这意味着您将TextBox
自身作为参数传递给Command
.
This leads to your Command
looking like this (if you're using a DelegateCommand
-style implementation in your VM):
这会导致您Command
看起来像这样(如果您DelegateCommand
在 VM 中使用-style 实现):
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();
}
}
This Command
implementation can be used for any TextBox
and best of all no code in the code-behind though you may want to put this in it's own class so there are no dependencies on System.Windows.Controls
in your VM. It depends on how strict your code guidelines are.
此Command
实现可用于TextBox
代码隐藏中的任何代码,最重要的是没有代码,尽管您可能希望将其放在它自己的类中,以便System.Windows.Controls
在您的 VM中没有依赖项。这取决于您的代码指南有多严格。
回答by Valery
This works for me:
这对我有用:
<TextBox
Text="{Binding Path=UserInput, UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Key="Return"
Command="{Binding Ok}"/>
</TextBox.InputBindings>
</TextBox>
回答by NielW
Answered here quite elegantly using attached behaviors, my preferred method for almost anything.
在这里使用附加行为非常优雅地回答,这是我几乎所有事情的首选方法。