zoukankan      html  css  js  c++  java
  • 信息系统开发平台OpenExpressApp 如何解决ComboBox.TextProperty绑定带来问题的来龙去脉

      前一阵子写了好几篇处理WPF内存泄漏和bug的blog,本篇继续,主要围绕一下ComboBox的绑定问题来讲,通过此bug的分析和解决过程,希望能给大家对处理bug带来一些思路。

    问题描述

      在OpenExpressApp中一直没有注意,测试人员提交了一个bug,现象是这样的:

    1. 选择左边任意一个列表项后,再选择一个PBS模板
    2. 切换左边列表项后,发现右边PBS模板显示为空白,没有内容

    发现问题

      既然是下拉列表操作后出现问题,那么我就在下拉操作时设置了一个断点,我加了一条更新ComboBox文本框内容的代码,想看看是否有效果:

    Snippet

    this._cmbGrid.GetBindingExpression(ComboBox.TextProperty).UpdateTarget()

      运行后竟然发现报空对象引用错误this._cmbGrid.GetBindingExpression(ComboBox.TextProperty)获取的是个空对象。如果熟悉OpenExpressApp的AutoUI设计的应该知道,在编辑器控件生成时会给生成控件进行Text绑定,按道理应该不会出现绑定不了的问题,既然出现了,那么就最可能是绑定出现了问题。

      那么问题处在哪呢?我突然想起,会不会是因为直接给ComboBox的Text属性赋值导致,由于直接赋值而清空绑定

    简化问题

      上面只是一个猜测,可能是Text赋值后导致,于是做了一个简单的程序,只是一个combox控件和button控件,在button上写了以下代码:

    Snippet

                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单元,发现执行到一段代码,具体代码还没有太看明白,我估摸着是清空绑定,如果有谁清晰的话回复一下吧。

    Snippet

                    // 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 == nullreturn;
                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."

    但要注意:这仅是清除单向绑定

    回顾

    1. 对于未知问题,可以通过现象猜测可能出现的点
    2. 如果项目本身复杂不易调试,可以针对问题点做一个简答Demo来验证问题点的猜测是否正确
    3. 通过.Net框架源码逐步调试可以看到内部代码执行流,比使用Reflector查看静态代码方便好用

    更多内容: 开源信息系统开发平台之OpenExpressApp框架.pdf

    欢迎转载,转载请注明:转载自周金根 [ http://zhoujg.cnblogs.com/ ]

    Snippet

  • 相关阅读:
    &与&&的区别
    jsp之response方法
    一个数组先按照某个属性的大小排序,如果大小一样的就按照名称排序
    CSS内部div设置上min-height或max-height滚动条就会出现在父元素上
    300行代码手写简单vue.js,彻底弄懂MVVM底层原理
    JavaScript简单手写观察者模式
    javascript中replace还可以这样玩
    VUE中通过改变key去更新局部dom
    element中select的change方法如何传多个参数
    react打包中不想要sourceMap,但是在命令里加'GENERATE_SOURCEMAP=false'后windows下报错'GENERATE_SOURCEMAP' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
  • 原文地址:https://www.cnblogs.com/zhoujg/p/1760485.html
Copyright © 2011-2022 走看看