我尝试使用代码优先技术将实体持久保存到数据库时遇到问题。例如,我正在做的事情你可以看看以下MSDN Sample。该应用程序通常按预期工作,除了一个案例。
如果我有一个现有的实体,我将它绑定到一个页面,该页面有一个TextBox来保存Title字段和一个AppBar图标来保存(类似于上面链接中的'New Task'屏幕截图,但是前面有值填充了具有双向绑定的现有实体),会出现以下问题。如果我选择了TextBox并且我更改了标题并点击了保存按钮,它会更新内存中的实体,以便完整列表现在显示新标题。但新标题不会持久保存到DB(它不会自动检测更改)。这很奇怪,不仅因为内存中的对象已经改变,而且因为如果我取消选择TextBox然后点击保存,它将保持对数据库的更改。
我已经在SO上看到了其他一些有关更改检测问题的问题,他们建议在save方法的开头添加this.Focus()
或关注其他一些元素。这对我的情况没有帮助。除非我点击屏幕取消选择TextBox并隐藏键盘(或按键盘上的Return键,我必须这样做.Focus()),否则它不会将对象检测为已更改。
我该如何解决这个问题?当键盘仍然可见时,究竟是什么阻止EF检测到物体变化?
答案 0 :(得分:1)
不确定我是否完全遵循您所描述的内容,但我认为问题是您绑定文本框的属性在文本框中触发TextChanged之前不会更新,并且在您离开文本框时首先执行此操作,如果你点击其他地方,它基本上会失去焦点。
对此及其行为有一个简单的解决方法。通过创建一个小行为,您可以强制文本框更新每次击键时的绑定 - 所以当您键入和键盘仍然存在时,所有内容都会更新。
行为:
/// <summary>
/// Update property on every keystroke in a textbox
/// </summary>
public class UpdateTextSourceTriggerBehavior : Behavior<TextBox>
{
protected override void OnAttached()
{
this.AssociatedObject.TextChanged += OnTextBoxTextChanged;
}
void OnTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
var bindingExpression = AssociatedObject.ReadLocalValue(TextBox.TextProperty) as BindingExpression;
if (bindingExpression != null)
{
bindingExpression.UpdateSource();
}
}
protected override void OnDetaching()
{
this.AssociatedObject.TextChanged -= OnTextBoxTextChanged;
}
}
现在只需将此行为附加到您的文本框中,如下所示:
<TextBox Text="{Binding YourPropertyName, Mode=TwoWay}">
<i:Interaction.Behaviors>
<UpdateTextSourceTriggerBehavior/>
</i:Interaction.Behaviors>
</TextBox>
这将使您的viewmodel上的属性始终保持更新状态,这样当您在文本框中输入后直接点击保存时,它将保存正确的值。希望它有所帮助!
干杯, 安德斯