当前位置:  开发笔记 > 编程语言 > 正文

按Enter键键合文本框

如何解决《按Enter键键合文本框》经验,为你挑选了5个好方法。

默认数据绑定TextBoxTwoWay,它只有在TextBox失去焦点时才将文本提交给属性.

当我按下?Enter键时,是否有任何简单的XAML方法可以使数据绑定发生TextBox.我知道在后面的代码中很容易做到,但想象一下,如果这TextBox是在一些复杂的内部DataTemplate.



1> Samuel Jack..:

您可以通过创建附加行为来使自己成为纯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();
        }
    }
}

然后在您的XAML中,将InputBindingsManager.UpdatePropertySourceWhenEnterPressedProperty属性设置Enter为按下该键时要更新的属性.像这样


(您只需要确保在XAML文件的根元素中包含"b"的xmlns clr-namespace引用,该文件指向您将InputBindingsManager放入哪个命名空间).


为了节省未来的读者几分钟的摆弄,我只是在我的项目中使用了这个,并且上面提供的示例XAML无法正常工作.每个字符更改都会更新源.将"UpdateSourceTrigger = PropertyChanged"更改为"UpdateSourceTrigger = Explicit"修复了该问题.现在一切正常.
键入实数时,UpdateSourceTrigger = PropertyChanged可能不方便.例如"3" 绑定到float时会导致问题.除了附加的行为之外,我建议不要指定UpdateSourceTrigger(或设置为LostFocus).这给了两全其美.
优秀作品!小巧的选择:当UpdatePropertySourceWhenEnterPressed从一个有效值更改为另一个有效值时,您将取消订阅并重新订阅PreviewKeyDown事件。相反,您只需要检查e.NewValue是否为null。如果不为空,则订阅;否则为空。否则,如果为null,则退订。

2> Ben..:

这就是我解决这个问题的方法.我创建了一个特殊的事件处理程序,进入后面的代码:

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事件处理程序:



事件处理程序使用其sender引用使其自己的绑定得到更新.由于事件处理程序是自包含的,因此它应该在复杂的DataTemplate中工作.现在可以将此一个事件处理程序添加到需要此功能的所有文本框中.


有人告诉我这是一个被低估的帖子.许多答案很受欢迎,因为它们是"XAML-y".但是在大多数情况下,这个似乎可以节省空间.
+1这还使您可以不理会UpdateSourceTrigger,以防万一您已经辛苦地使TextBox绑定按照您想要的方式运行(使用样式,验证,双向)等,但是当前仅在按Enter键后才收到输入。
这是我发现的最干净的方法,我认为应该将其标记为答案。添加了对发件人的其他空检查,对Key.Return的检查(我的键盘上的Enter键返回Key.Return),以及Keyboard.ClearFocus()在更新source属性后从TextBox移除焦点。我已对等待同行评审的答案进行了编辑。
同意以上评论。但是对我来说KeyDown事件更合适

3> Matt Hamilto..:

我不相信有任何"纯XAML"方式来做你所描述的.您可以通过设置UpdateSourceTrigger属性来设置绑定,以便在TextBox中的文本发生更改时(而不是在TextBox失去焦点时)更新它,如下所示:


如果你将UpdateSourceTrigger设置为"Explicit"然后处理TextBox的PreviewKeyDown事件(寻找Enter键),那么你可以实现你想要的,但它需要代码隐藏.也许某种附加属性(类似于我的EnterKeyTraversal属性)woudld适合你.


这个答案可能比标记为答案的答案简单,但它有一些局限性.想要在绑定属性的set-function中进行某种检查的图像(检查输入是否有效).您不希望在用户按下每个键后调用该检查功能,是否(特别是当功能需要一些时间时).

4> Ryan Versaw..:

您可以轻松地创建自己的继承自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):



在WPF/Silverlight中,你永远不应该使用继承 - 它会混淆样式并且不像附加行为那样灵活.例如,对于附加行为,您可以在同一文本框中同时具有Watermark和UpdateOnEnter.

5> toadflakz..:

如果将Ben和ausadmin的解决方案结合起来,最终会得到一个非常适合MVVM的解决方案:


    
        
    

...这意味着你将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();
        }
    }

这个Command实现可以用于TextBox代码隐藏中的任何代码,尽管你可能想把它放在它自己的类中,所以System.Windows.Controls你的VM 中没有依赖.这取决于您的代码指南的严格程度.

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有