信息系统开发平台OpenExpressApp - 如何解决ComboBox.TextProperty绑定带来问题的来龙去脉
前一阵子写了好几篇处理WPF内存泄漏和bug的blog,本篇继续,主要围绕一下ComboBox的绑定问题来讲,通过此bug的分析和解决过程,希望能给大家对处理bug带来一些思路。
问题描述
在OpenExpressApp中一直没有注意,测试人员提交了一个bug,现象是这样的:
- 选择左边任意一个列表项后,再选择一个PBS模板
- 切换左边列表项后,发现右边PBS模板显示为空白,没有内容
发现问题
既然是下拉列表操作后出现问题,那么我就在下拉操作时设置了一个断点,我加了一条更新ComboBox文本框内容的代码,想看看是否有效果:
this._cmbGrid.GetBindingExpression(ComboBox.TextProperty).UpdateTarget()
运行后竟然发现报空对象引用错误,this._cmbGrid.GetBindingExpression(ComboBox.TextProperty)获取的是个空对象。如果熟悉OpenExpressApp的AutoUI设计的应该知道,在编辑器控件生成时会给生成控件进行Text绑定,按道理应该不会出现绑定不了的问题,既然出现了,那么就最可能是绑定出现了问题。
那么问题处在哪呢?我突然想起,会不会是因为直接给ComboBox的Text属性赋值导致,由于直接赋值而清空绑定
简化问题
上面只是一个猜测,可能是Text赋值后导致,于是做了一个简单的程序,只是一个combox控件和button控件,在button上写了以下代码:
cb.SetBinding(ComboBox.TextProperty, b);
cb.GetBindingExpression(ComboBox.TextProperty).UpdateTarget();
cb.Text = "111";
cb.GetBindingExpression(ComboBox.TextProperty).UpdateTarget();
发现果然是在Text赋值后就会清空TextProperty的数据绑定。为了查看在哪里清除,我用了在下载.Net4 Framework源码,查找OpenExpressApp中DataGrid枚举值更新错误的原因中介绍的方法,逐步调试到DependencyObject单元,发现执行到一段代码,具体代码还没有太看明白,我估摸着是清空绑定,如果有谁清晰的话回复一下吧。
// detach the old expression, if applicable
if (currentExpr != null)
{
// CALLBACK
DependencySource[] currentSources = currentExpr.GetSources();
UpdateSourceDependentLists(this, dp, currentSources, currentExpr, false); // Remove
// CALLBACK
currentExpr.OnDetach(this, dp);
currentExpr.MarkDetached();
entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);
}
解决问题
既然知道了原因是TextBinding被清空了,那么剩下的就是我们如何在框架中处理了,解决这个问题很简单,每个属性编辑器都有一个View对象,那么我们只要在每次切换列表时重新绑定一次就好了,修改代码如下:
public LookupListPropertyEditor(BusinessObjectPropertyInfo propertyInfo, IObjectView view)
: base(propertyInfo, view)
{
this.View.CurrentObjectChanged += new EventHandler(View_CurrentObjectChanged);
}
void View_CurrentObjectChanged(object sender, EventArgs e)
{
CreateTextBinding();
}
//由于直接对ComboBox.Text直接赋值,导致TextBinding Detach,所以需要手动新增绑定
private void CreateTextBinding()
{
if (_cmbGrid == null) return;
var bindExpr = this._cmbGrid.GetBindingExpression(ComboBox.TextProperty);
if (bindExpr == null)
{
Binding textBinding = new Binding();
this.PrepareBinding(textBinding);
PrepareBinding(textBinding);
this._cmbGrid.SetBinding(ComboBox.TextProperty, textBinding);
}
else
bindExpr.UpdateTarget();
}
知识点
解决问题后,在《WPF揭秘》一书196页中发现写到:
另一种清除绑定的方式是直接为目标属性设置一个新的值,例如: currentFolder.Text = "I am no longer receiving updates."
但要注意:这仅是清除单向绑定
回顾
- 对于未知问题,可以通过现象猜测可能出现的点
- 如果项目本身复杂不易调试,可以针对问题点做一个简答Demo来验证问题点的猜测是否正确
- 通过.Net框架源码逐步调试可以看到内部代码执行流,比使用Reflector查看静态代码方便好用
更多内容: 开源信息系统开发平台之OpenExpressApp框架.pdf
欢迎转载,转载请注明:转载自周金根 [ http://zhoujg.cnblogs.com/ ]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2006-06-18 业务、技术和语言的关系