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

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

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

【问题讨论】:

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

标签: xaml silverlight windows-phone-7 data-binding


【解决方案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 项目)。

    现在如何使用它:

    1. 向您的 Windows Phone 项目添加对 System.Windows.Interactivity 程序集的引用。
    2. 在要使用该行为的每个页面中,添加对程序集的 XAML 引用: xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    3. 在您要应用 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 可能会更好。但是这种解决方案仍然将您限制在一个控件中,这就是我完全不同意它的原因之一。如果我们希望在另一个控件上具有相同的行为怎么办?
        • 网址已过期
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-07-29
        • 2023-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-13
        • 2017-11-07
        相关资源
        最近更新 更多