SUPER_CRJ 发表于 2020-6-16 15:32:27

C#的TextBoxChanged导致TextBox输入不正常

本帖最后由 SUPER_CRJ 于 2020-6-16 15:35 编辑

查了一天了。
具体情况是:
因为要实时解析文本框中的数据。所以用了:TextBoxChanged事件。
但是此时:文本框则不正常了:
1:删除里面的内容,要删除两下,才能成功。而且光标移动到了开头。
2:输入内容也是:输入两下才可以。
仔细检查了相关代码:根本没有可以改变Text的代码。十分费解!!



代码如下(已经过压缩):
      { // 如果增加多个事件,则函数看来会比较乱。所以把众多事件统一处理,简化代码!
            for( int i = 0;i<1;i++ )
            { // 总共5个
                { // 取数据
                  string inputData = (tabPage3.Controls["txb_sendData" + i.ToString()] as TextBox).Text;
                  string str = Regex.Replace(inputData, @"((\d\s)|(\d\d))(\s*)", "$0" + " ");
                  MatchCollection mc = Regex.Matches(str, @"\b+\b");
                  List<byte> buf = new List<byte>();
                  foreach (Match m in mc)
                  {
                        buf.Add(byte.Parse(m.Value, System.Globalization.NumberStyles.HexNumber));
                  }
                  if (buf.Count > 8)
                  {
                        showMessageBoxLanguage("第 " + i.ToString() + " 行输入数据超过8字节,请重新输入", "Line " + i.ToString() + " :Input data exceeding 8 bytes, please reenter");
                  }
                  masterSend.dataLen = buf.Count;
                  Array.Copy(buf.ToArray(), masterSend.dataBuf, buf.Count);
                }
                { // 出校验值
                if (masterSend.checkWay == 0)
                { // 标准校验
                  masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, 0);
                  (tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");
                }
                  else if (masterSend.checkWay == 1)
                  { // 增强校验
                        masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, idParityQueryWay(masterSend.ID));
                        (tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");
                  }
                  else
                  { // 自定义校验
                        masterSend.checkValue = byte.Parse((tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text);
                  }
                }
            }
      }

源代码:

wudicgi 发表于 2020-6-16 15:58:34

这里修改了 txb_checkValueX 控件的 Text 属性
// 标准校验
masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, 0);
(tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");

而 TextBox 控件的 Text 属性值发生变化时,会发送一个 message:
// System.Windows.Forms.TextBoxBase
using System.ComponentModel;
using System.Drawing.Design;



public override string Text
{
        get
        {
                return base.Text;
        }
        set
        {
                if (value != base.Text)
                {
                        base.Text = value;
                        if (base.IsHandleCreated)
                        {
                                SendMessage(185, 0, 0);
                        }
                }
        }
}


看参数不确定这是能否区分出来目标对象是 txb_checkValueX 还是 txb_sendDataX

其实这种问题自己一点一点注释代码,反复试一试应该能先定位到出问题的代码

wudicgi 发表于 2020-6-16 16:01:14

SendMessage(185, 0, 0) 的 185 应该是这个消息

EM_SETMODIFY := 0xB9

https://wiki.winehq.org/List_Of_Windows_Messages
https://docs.microsoft.com/en-us/windows/win32/controls/em-setmodify

SUPER_CRJ 发表于 2020-6-16 16:16:03

wudicgi 发表于 2020-6-16 15:58
这里修改了 txb_checkValueX 控件的 Text 属性




测试不行
把代码屏蔽:
//(tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");

仍然不能解决问题。
我的附件已上传了源代码,可不可以帮看下。

wudicgi 发表于 2020-6-16 17:21:17

SUPER_CRJ 发表于 2020-6-16 16:16
测试不行
把代码屏蔽:



我就是打开项目试的,注释掉后边这行在删除时就正常了

SUPER_CRJ 发表于 2020-6-16 20:22:55

wudicgi 发表于 2020-6-16 17:21
我就是打开项目试的,注释掉后边这行在删除时就正常了

不行!
我把这句换成其它的功能一致的也不行!!
证明应该不是这种原因造成的。
好纠结,完全没有头绪!

masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, 0);
txb_checkValue0.Text = masterSend.checkValue.ToString("X");

SUPER_CRJ 发表于 2020-6-16 20:24:16

wudicgi 发表于 2020-6-16 17:21
我就是打开项目试的,注释掉后边这行在删除时就正常了

另外:请问
注释掉后边这行在删除?这是什么样的操作,不太懂。。。{:smile:}

hcambridge 发表于 2020-6-16 20:31:29

改用key-up或者key-press事件试试

wudicgi 发表于 2020-6-16 21:41:19

SUPER_CRJ 发表于 2020-6-16 20:24
另外:请问
注释掉后边这行在删除?这是什么样的操作,不太懂。。。...

注释掉后边这行(后,)在(文本框中进行)删除时就正常了

wudicgi 发表于 2020-6-16 21:44:17

SUPER_CRJ 发表于 2020-6-16 20:22
不行!
我把这句换成其它的功能一致的也不行!!
证明应该不是这种原因造成的。


我从 Win10 换到 Win8.1 的另一台电脑上,还是 VS2017,同样注释掉那行代码还是能消除这个问题


                { // 出校验值
                if (masterSend.checkWay == 0)
                { // 标准校验
                  masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, 0);
//                  (tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");            // 注释掉此行,或者下边 else if 里那行也一块注释掉
                }
                  else if (masterSend.checkWay == 1)
                  { // 增强校验
                        masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, idParityQueryWay(masterSend.ID));
                        (tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");
                  }
                  else
                  { // 自定义校验
                      //try
                      //{
                        masterSend.checkValue = byte.Parse((tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text);
                        //}
                        //catch { }
                  }
                }

zyqcome 发表于 2020-6-16 21:56:07

本帖最后由 zyqcome 于 2020-6-16 22:14 编辑

改成失去焦点事件?

-----

楼主,都这么多控件了,不要硬钢了,

这个是你遍历控件的时候,鼠标焦点丢失了,

我的建议是,要么不要用遍历这些控件,这样焦点至少在这个控件,

当然,
有个更简单的,增加一个 button,专门来确认修改


希望能帮到你

7073640 发表于 2020-6-16 23:07:29

加个timeout,只有输入超时才去校验文本内容,或者keydown事件去校验

wudicgi 发表于 2020-6-17 00:48:25

其实话说回来,比较好的方式应该是正常的时候在 TextBox LostFocus 时才验证内容,在经过验证内容不合法时才在 TextChanged 或 KeyUp 时就马上验证内容
另外每次只验证当前 TextBox, 而不是所有 TextBox
在执行类似提交的操作时才一次性验证所有 TextBox

zhongsandaoren 发表于 2020-6-17 08:24:27

一般都是执行操作前,统一进行合法性检验。省事,也够用。

SUPER_CRJ 发表于 2020-6-17 10:17:34

zyqcome 发表于 2020-6-16 21:56
改成失去焦点事件?

-----


我上传的代码中实际并没有遍历控件。其中几个参数修改了。
其实最终只是:获取了textBox中的数值解析,然后再改另外一个textBox中的数值。并没有访问其它控件。
难道仅仅是:访问了其它一个控件就产生了这样的效果?
(因为是实时解析出值,所以加了一个按键感觉有点:多此一举。)

下面是我上传的代码,麻烦可以再参考下。

SUPER_CRJ 发表于 2020-6-17 10:17:53

wudicgi 发表于 2020-6-17 00:48
其实话说回来,比较好的方式应该是正常的时候在 TextBox LostFocus 时才验证内容,在经过验证内容不合法时 ...

好的,谢谢。
TextBox LostFocus 不方便使用,因为要实时解析出数据。

可以考虑:KeyUp事件,因为之前测试KeyPress没有出现这样的问题。

另外有一点:我修改的代码中其实只检测了一个TextBox,并没有你说的遍历所有。但是也出了这样的问题,所以我想到原因。
(代码我上传到了15楼)

SUPER_CRJ 发表于 2020-6-17 10:20:59

wudicgi 发表于 2020-6-16 21:44
我从 Win10 换到 Win8.1 的另一台电脑上,还是 VS2017,同样注释掉那行代码还是能消除这个问题




如果是改变了属性。
我把你备注掉的语句直接改为:
txb_checkValue0.Text = strTmp; //strTmp是结果
为什么也还是不行!同样的效果。

wudicgi 发表于 2020-6-17 11:30:48

SUPER_CRJ 发表于 2020-6-17 10:20
如果是改变了属性。
我把你备注掉的语句直接改为:



那你试试注释掉其他的代码,看是哪块有印象
我这试出来就是这块

zyqcome 发表于 2020-6-17 18:08:10

SUPER_CRJ 发表于 2020-6-17 10:17
我上传的代码中实际并没有遍历控件。其中几个参数修改了。
其实最终只是:获取了textBox中的数值解析,然 ...

确实是输入焦点失去了,我在回复中提到遍历出自

string inputData = (tabPage3.Controls["txb_sendData" + i.ToString()] as TextBox).Text;

这里读了其他的控件

今天仔细看了一下,是另一个 edit 控件引起的



这两个都是 edit 这样在这里

                  if (masterSend.checkWay == 0)
                  { // 标准校验
                        masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, 0);
                        //masterSend.checkValue = 99;
                        //(tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");
                        string strTmp = masterSend.checkValue.ToString("X");
                        txb_checkValue0.Text = strTmp; //AAAA
                  }

//AAAA 这个地方,输入的焦点到了 txb_checkValue0 当你再次修改 txb_sendData0 的时候,就需要点两次才能进去,一次激活输入,就是是光标闪烁,一个真正修改

我想到的解决办法

把txb_checkValue0 换成 label 既然 校验值是算出来的,没必要修改






SUPER_CRJ 发表于 2020-6-17 20:00:32

zyqcome 发表于 2020-6-17 18:08
确实是输入焦点失去了,我在回复中提到遍历出自




非常感谢。
应该就是修改另外一个textBox导致的。
但是:另外一个textBox在另外一种模式下,还需要使用。所以不能换成label。
不过终于找到问题的原因了。

我现在用的解决方法是:把textChanged换成keyUp事件就好了。

SUPER_CRJ 发表于 2020-6-17 20:01:51

hcambridge 发表于 2020-6-16 20:31
改用key-up或者key-press事件试试

key-up事件测试可以的。
key-Press不行,因为此时按下的键还没有真正输入到TextBox中。

armstrong 发表于 2020-6-18 21:27:20

分析了你的源码,发现跟你的复杂的数据绑定有关,你最好取消txb_checkValue0-n这些控件的数据绑定;数据流回路导致的。
文字描述这个过程太复杂,你自己按照我的思路调调看。
页: [1]
查看完整版本: C#的TextBoxChanged导致TextBox输入不正常