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
?我收到来自GetBindingExpression
的null
。【参考方案2】:
下载 Charles Petzold 的免费书籍Programming Windows Phone 7。在第 387 页,他谈到了如何做到这一点。
基本上,将Binding
的UpdateSourceTrigger
属性设置为Explicit
。然后,在TextBox
的TextChanged
回调中,更新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就报错!
在 WPF + MVVM +Binding + UserInput 中的 TextBox “预期格式为 DD/MM/YYYY”
WPF Binding Mode,UpdateSourceTrigger