假设我有一个带有文本框和确定/取消按钮的模式对话框。它建立在 MVVM 之上——即它有一个 ViewModel 对象,该对象具有文本框绑定(bind)到的字符串属性。
例如,我在文本框中输入了一些文本,然后捕获我的鼠标并单击“确定”。一切正常:在单击时,文本框失去焦点,这导致绑定(bind)引擎更新 ViewModel 的属性。我得到了我的数据,大家都很高兴。
现在假设我不使用我的鼠标。相反,我只是按键盘上的 Enter。这也会导致“确定”按钮“单击”,因为它被标记为 IsDefault="True"。但猜猜怎么了?在这种情况下,文本框不会失去焦点,因此,绑定(bind)引擎仍然天真无知,我没有得到我的数据。该死!
同一场景的另一种变体:假设我在主窗口中有一个数据输入表单,向其中输入一些数据,然后按 Ctrl+S 键“保存”。你猜怎么着?我的最新条目没有保存!
使用 UpdateSourceTrigger=PropertyChanged 可以稍微补救,但这并不总是可能的。
一个明显的例子是将 StringFormat 与绑定(bind)一起使用 - 当我尝试输入文本时,文本不断跳回“已格式化”状态。
我自己遇到的另一种情况是,当我在 View 模型的属性 setter 中进行一些耗时的处理时,我只想在用户“完成”输入文本时执行它。
这似乎是一个永恒的问题:我记得从很久以前开始尝试系统地解决它,自从我开始使用交互式界面以来,但我从未完全成功。过去,我总是以使用某种技巧告终——比如,向每个“演示者”(如“MVP”)添加一个“EnsureDataSaved”方法,并在“关键”点调用它,或类似的东西。 ..
但是有了 WPF 的所有炫酷技术以及空洞的炒作,我预计他们会想出一些好的解决方案。
最佳答案
在关键点,您可以强制绑定(bind)推送到您的 View 模型:
var textBox = Keyboard.FocusedElement as TextBox;
BindingOperations.GetBindingExpression(textBox, TextBox.TextProperty).UpdateSource();
编辑:
好吧,既然你不想被黑客攻击,我们就不得不面对丑陋的事实:
我们可以使用的类比是文本编辑器。如果应用程序是一个绑定(bind)到磁盘文件的巨大文本框,则每次击键都会导致写入整个文件。甚至不需要储蓄的概念。这是错误的正确但非常低效。我们都立即看到 View 模型需要公开一个缓冲区供 View 绑定(bind),这在我们的 View 模型中重新引入了保存和强制状态处理的概念。
然而,我们发现这仍然不够有效。即使对于中等大小的文件,在每次击键时更新整个文件缓冲区的开销也变得难以忍受。接下来,我们在我们的 View 模型中公开命令以有效地操作缓冲区,而不是真正地与 View 交换整个缓冲区。
因此我们得出结论,为了通过纯 MVVM 实现效率和响应能力,我们需要公开一个高效的 View 模型。这意味着所有文本框都可以绑定(bind)到属性而不会产生不良影响。 但是,这也意味着您必须将状态下推到 View 模型中来处理它。这没关系,因为 View 模型不是模型;它的工作是处理 View 的需求。
的确,我们可以利用绑定(bind)焦点更改等快捷方式来快速构建用户界面原型(prototype)。但是绑定(bind)焦点变化可能会在实际应用程序中产生负面影响,如果是这样,那么我们根本不应该使用它。
有什么选择?公开一个对频繁更新友好的属性。调用它与调用旧的低效属性相同。使用 slow 属性和依赖于 View 模型状态的逻辑来实现你的 fast 属性。 View 模型获取保存命令。它知道 fast 属性是否已被推送到 slow 属性。它可以决定是否将慢属性同步到模型的时间和位置。
但是您说,我们不是刚刚将 hack 从 View 转移到了 View 模型吗?不,我们失去了一些优雅和简单,但回到文本编辑器类比。我们必须解决问题,解决问题是 View 模型的工作。
如果我们想使用纯 MVVM 并且我们想要效率和响应能力,那么像让我们避免在元素失去焦点之前更新绑定(bind)源这样的蹩脚启发式方法将无济于事。他们引入的问题与解决的问题一样多。在那种情况下,我们应该让 View 模型完成它的工作,即使这意味着增加复杂性。
假设我们接受它,我们如何管理复杂性?我们可以实现一个通用的包装实用程序类来缓冲 slow 属性,并允许 View 模型 Hook 它的 get 和 set 方法。我们的实用程序类可以自动注册保存命令事件,以减少 View 模型中的样板代码量。
如果我们做对了,那么 View 模型中所有足够快以用于属性更改绑定(bind)的部分都将保持不变,而其他值得提出问题“这个属性是否也是如此”的部分减缓?”将有少量的代码来解决这个问题,而且 View 也不是明智的。
关于c# - 如何不丢失绑定(bind)源更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4677693/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf
我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U
这太简单了,太荒谬了,我在任何地方都找不到关于它的任何信息,包括API文档和Rails源代码:我有一个:belongs_to关联,我开始理解当您没有关联时您在Controller中调用的正常模型方法与您有关联时调用的方法略有不同。例如,我的关联在创建Controller操作时运行良好:@user=current_user@building=Building.new(params[:building])respond_todo|format|if@user.buildings.create(params[:building])#etcetera但我找不到关于更新如何工作的文档:@user
升级到OSXYosemite后,我现有的pow.cx安装不起作用。升级到最新的pow.cx无效。通过事件监视器重新启动它也没有成功。 最佳答案 卸载(!)并重新安装解决了这个问题。curlget.pow.cx/uninstall.sh|shcurlget.pow.cx|sh 关于ruby-on-rails-OSXYosemite更新破坏了pow.cx,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/q