TextBox Binding TwoWay 直到焦点丢失 WP7 才会更新

Posted

技术标签:

【中文标题】TextBox Binding TwoWay 直到焦点丢失 WP7 才会更新【英文标题】:TextBox Binding TwoWay Doesn't Update Until Focus Lost WP7 【发布时间】:2011-07-30 23:57:05 【问题描述】:

我有一个页面,其中包含一些用于数据输入的文本框。文本框的绑定设置为TwoWay。只有当文本框失去焦点时,我的视图模型中的数据才会更新。如果我单击一个按钮,例如保存,并且文本框仍然具有焦点,则文本框中的更改不会在我的视图模型中更改保存事件。

有没有办法让绑定在失去焦点之前保存文本框的值?还是我需要在保存事件中做些什么?

【问题讨论】:

在这里您可以找到更新 TextChanged 事件绑定的有效解决方案:***.com/a/4833196/928955 WP8 上的同样问题,@StefanWick 的回答为我解决了。 【参考方案1】:

我假设您的保存按钮是 ApplicationBarButton(不是普通按钮)。对于普通按钮,它只会起作用,因为它们会获得焦点,因此数据绑定将开始。

对于手机上的 ApplicationBarButtons,它有点不同,因为它们不会将焦点从客户端应用程序上移开。为确保在单击“保存”按钮时启动数据绑定,您可以在处理程序中添加以下代码:

object focusObj = FocusManager.GetFocusedElement();
if (focusObj != null && focusObj is TextBox)

    var binding = (focusObj as TextBox).GetBindingExpression(TextBox.TextProperty);
    binding.UpdateSource();

【讨论】:

谢谢。很高兴知道原因。 谢谢。每次更新文本属性时,我们都会自动保存数据结构,但每次击键都发生这种情况感觉不对。 感谢它帮助了我,因为我不使用 MVVM 灯。 终于找到了实际的解释,非常感谢! 这是否适用于x:Bind?我收到来自GetBindingExpressionnull【参考方案2】:

下载 Charles Petzold 的免费书籍Programming Windows Phone 7。在第 387 页,他谈到了如何做到这一点。

基本上,将BindingUpdateSourceTrigger 属性设置为Explicit。然后,在TextBoxTextChanged 回调中,更新Binding 源。

【讨论】:

【参考方案3】:

尝试将UpdateSourceTrigger 属性设置为“PropertyChanged”

喜欢这个

Property="Binding PropertyBinding, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged"

【讨论】:

just Property="Binding PropertyBinding, UpdateSourceTrigger=PropertyChanged" as twoway 是默认的【参考方案4】:

您可以使用Prism Library for WP7 中的UpdateTextBindingOnPropertyChanged 行为在文本更改而不是失去焦点时更新绑定值。

【讨论】:

我已经在使用 MVVM Light 并且不想仅仅为此包含 Prism。 :( 嗯,源代码也是可用的,所以你可以只包含那个文件;) 是的,这就是我现在正在查看的内容。我没有意识到 WP7 的 Prism 到底有多轻。我可能需要查找 Prism 和 MVVM Light 之间的差异。 Prism 似乎有一些额外的东西我需要使用。 这是个人喜好 :) WP7 的 Prism 比 Silverlight 或 WPF 轻很多,但可以满足您的大部分需求。 MVVM Light 也有一些优点,尤其是 EventToCommand;取决于你需要什么。 我一直在寻找是否可以完全切换到 Prism,因为它看起来几乎拥有我需要的一切。如果没有办法在 Prism 中执行 EventToCommand,也许我会同时使用这两个框架。它们看起来都很小。【参考方案5】:

我正朝着@Praetorian 的相反方向前进。

您的TextBox 的默认UpdateSourceTrigger 值为LostFocus。这意味着该值仅在失去焦点时才会推送到您的 ViewModel 属性。

您可以将 UpdateSourceTrigger 设置为 PropertyChanged:

<TextBox UpdateSourceTrigger="PropertyChanged" Text="Binding TextViewModelProperty" />

来自http://msdn.microsoft.com/en-us/library/system.windows.data.binding.updatesourcetrigger.aspx:

UpdateSourceTrigger 值之一。 默认为 Default,返回 默认的 UpdateSourceTrigger 值 目标依赖属性。 但是,大多数的默认值 依赖属性是 PropertyChanged,而文本 属性的默认值为 失去焦点。

请记住,这意味着由更新此属性触发的任何事情都会更频繁地发生(基本上是每次按键,而不是TextBox 失去焦点时的一次“刷新”)。

希望有帮助!

【讨论】:

Silverlight 不支持“UpdateSourceTrigger”的“PropertyChanged”值。您已链接 WPF 主题,该主题不适用于 WP7。 糟糕,我是 WPF 人,所以我总是忘记这一点!对不起! 将 Text 属性设置为 Text="Binding TextViewModelProperty,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged" 对我有用(我使用的是 SL5)。【参考方案6】:

这是 Derek 建议的 Microsoft 解决方案的快速访问答案。无需下载和筛选所有 Prism 内容,只需将此类复制到您的项目中,然后按照以下步骤激活它:

UpdateBindingOnPropertyChangedBehviour.cs

using System;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Interactivity;

namespace MyCompany.MyProduct

    /// <summary>
    /// Custom behavior that updates the source of a binding on a text box as the text changes.
    /// </summary>
    public class UpdateTextBindingOnPropertyChanged : Behavior<TextBox>
    
        /// <summary>
        /// Binding expression this behavior is attached to.
        /// </summary>
        private BindingExpression _expression;

        /// <summary>
        /// Called after the behavior is attached to an AssociatedObject.
        /// </summary>
        /// <remarks>
        /// Override this to hook up functionality to the AssociatedObject.
        /// </remarks>
        protected override void OnAttached()
        
            base.OnAttached();

            // Hook events to change behavior
            _expression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
            AssociatedObject.TextChanged += OnTextChanged;
        

        /// <summary>
        /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
        /// </summary>
        /// <remarks>
        /// Override this to unhook functionality from the AssociatedObject.
        /// </remarks>
        protected override void OnDetaching()
        
            base.OnDetaching();

            // Un-hook events
            AssociatedObject.TextChanged -= OnTextChanged;
            _expression = null;
        

        /// <summary>
        /// Updates the source property when the text is changed.
        /// </summary>
        private void OnTextChanged(object sender, EventArgs args)
        
            _expression.UpdateSource();
        
    

这基本上是 Microsoft Prism 4.1 代码的清理版本(如果您想浏览其余部分,请参阅 Silverlight\Prism.Interactivity 项目)。

现在如何使用它:

    向您的 Windows Phone 项目添加对 System.Windows.Interactivity 程序集的引用。 在要使用该行为的每个页面中,添加对程序集的 XAML 引用: xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

    在您要应用 bahvior 的每个 TextBox 的 XAML 中(已将 TwoWay 绑定到您的源属性),添加以下内容:

    注意:您的代码中的“my:”前缀可能不同。它只是您添加行为类的命名空间引用。

【讨论】:

【参考方案7】:

我还没有尝试过@Praetorian 的答案,所以如果效果很好,那就这样做 - 否则,使用 KeyUp 和 TextChanged 事件来更新绑定源。

【讨论】:

【参考方案8】:

此链接有一个在 WinRT 中完美运行的解决方案。他继承了 TextBox 并添加了一个新属性:BindableText。

http://www.familie-smits.com/post/2012/07/29/UpdateSourceTrigger-in-WinRT.aspx

【讨论】:

扩展文本框听起来不是个好主意。这实际上是一个非常糟糕的主意。事实上,这是最糟糕的想法。 AttachProperty 可能会更好。但是这种解决方案仍然将您限制在一个控件中,这就是我完全不同意它的原因之一。如果我们希望在另一个控件上具有相同的行为怎么办? 网址已过期

以上是关于TextBox Binding TwoWay 直到焦点丢失 WP7 才会更新的主要内容,如果未能解决你的问题,请参考以下文章

C#/WPF高手进!ComboBox.ItemTemplate用TextBlock正常,用TextBox就报错!

TwoWay 绑定不是真的 Two Way 吗?

在 WPF + MVVM +Binding + UserInput 中的 TextBox “预期格式为 DD/MM/YYYY”

WPF Binding Mode,UpdateSourceTrigger

如何使用 Binding with Dependency Property 链接属性

WPF-Binding的源