Sam*_*ack 130
您可以通过创建附加行为来使自己成为纯XAML方法.
像这样的东西:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在您的XAML中,将InputBindingsManager.UpdatePropertySourceWhenEnterPressedProperty属性设置Enter为按下该键时要更新的属性.像这样
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}"
b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text"/>
Run Code Online (Sandbox Code Playgroud)
(您只需要确保在XAML文件的根元素中包含"b"的xmlns clr-namespace引用,该文件指向您将InputBindingsManager放入哪个命名空间).
Ben*_*Ben 47
这就是我解决这个问题的方法.我创建了一个特殊的事件处理程序,进入后面的代码:
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(); }
}
}
Run Code Online (Sandbox Code Playgroud)
然后我将其添加为XAML中的KeyUp事件处理程序:
<TextBox Text="{Binding TextValue1}" KeyUp="TextBox_KeyEnterUpdate" />
<TextBox Text="{Binding TextValue2}" KeyUp="TextBox_KeyEnterUpdate" />
Run Code Online (Sandbox Code Playgroud)
事件处理程序使用其sender引用使其自己的绑定得到更新.由于事件处理程序是自包含的,因此它应该在复杂的DataTemplate中工作.现在可以将此一个事件处理程序添加到需要此功能的所有文本框中.
Mat*_*ton 46
我不相信有任何"纯XAML"方式来做你所描述的.您可以通过设置UpdateSourceTrigger属性来设置绑定,以便在TextBox中的文本发生更改时(而不是在TextBox失去焦点时)更新它,如下所示:
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}" />
Run Code Online (Sandbox Code Playgroud)
如果你将UpdateSourceTrigger设置为"Explicit"然后处理TextBox的PreviewKeyDown事件(寻找Enter键),那么你可以实现你想要的,但它需要代码隐藏.也许某种附加属性(类似于我的EnterKeyTraversal属性)woudld适合你.
Rya*_*saw 25
您可以轻松地创建自己的继承自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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
可能有办法绕过这一步,但否则你应该像这样绑定(使用Explicit):
<custom:SubmitTextBox
Text="{Binding Path=BoundProperty, UpdateSourceTrigger=Explicit}" />
Run Code Online (Sandbox Code Playgroud)
toa*_*akz 11
如果将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>
Run Code Online (Sandbox Code Playgroud)
...这意味着你将TextBox自己作为参数传递给Command.
这导致您Command看起来像这样(如果您DelegateCommand在VM中使用a- 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();
}
}
Run Code Online (Sandbox Code Playgroud)
这个Command实现可以用于TextBox代码隐藏中的任何代码,尽管你可能想把它放在它自己的类中,所以System.Windows.Controls你的VM 中没有依赖.这取决于您的代码指南的严格程度.
这不是原始问题的答案,而是@Samuel Jack已接受答案的延伸。我在自己的应用程序中执行了以下操作,并对塞缪尔解决方案的优雅感到敬畏。它非常干净,并且非常可重用,因为它可以在任何控件上使用,而不仅仅是TextBox. 我认为这应该与社区分享。
如果您有一个包含 1000 个窗口的窗口TextBoxes,所有窗口都需要在 Enter 时更新绑定源,则可以通过将下面的 XAML 包含到您的窗口中,Window Resources而不是将其附加到每个 TextBox 来将此行为附加到所有窗口。当然,首先您必须按照塞缪尔的帖子实现附加行为。
<Window.Resources>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Setters>
<Setter Property="b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed" Value="TextBox.Text"/>
</Style.Setters>
</Style>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)
Grid如果需要,您始终可以通过将样式放入包含目标文本框的窗口子元素之一(即 a )的资源中来限制范围。
小智 5
在我看来,这是一种非常简单的方法,并且比添加 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>
Run Code Online (Sandbox Code Playgroud)
那么命令方法是
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
Run Code Online (Sandbox Code Playgroud)
并且 TextBox 绑定到 Property
Public Property Txt1 As String
Get
Return _txt1
End Get
Set(value As String)
_txt1 = value
OnPropertyChanged("Txt1")
End Set
End Property
Run Code Online (Sandbox Code Playgroud)
到目前为止,这似乎工作得很好,并捕获了文本框中的 Enter Key 事件。