c# datagridviewtextboxcolumn怎么限制输入的字节数(中文占两个字节)?

简简单单相爱8 2019-05-26 08:29:12
我的dgv中有一列类型是textboxcolumn的单元格,我想限制用户输入的字节数(5个字节),比如数字输入“12345”,中文应只能输入“一二”两个汉字,但控件自身带的Maxinputlength属性是按照长度来限制的(一个汉字或字母均被看做一个长度),我想要实现按照字节数来限制,其它功能与Maxinputlength功能一致,复制粘贴均应不受影响,我看网上有Textbox控件增加了一个MaxByteLength实现此功能,不知dgv里的应该怎么写?最好有代码或工程,本人小白,非常感谢!!!
...全文
1503 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 16 楼 秋的红果实的回复:
dgv里面,用cellEndEdit总可以吧,

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
    {
        string temp = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
        getTargetStr(temp,5); //我上面写的那个方法
    }
}

你非要那个固定长的效果,那个列,动态加载textbox,如下

private void Form1_Load(object sender, EventArgs e)
{
    TextBox text = new TextBox();
    text.Text = "hahha";
    text.Name = "tbx1"; //一万个,就用tbx10000
    text.TextChanged += new EventHandler(setText);

    dataGridView1.Rows[0].Cells[0].Value = text;
    dataGridView1.Controls.Add(text);

}
private void setText(object sender,EventArgs e)
{
    TextBox currText = (TextBox)sender;
    if(currText.Text.Trim()!=string.Empty)
    {
        currText.Text = getTargetStr(currText.Text.Trim(), 5);
        currText.Select(5, 0);
    }
}

我这没数据,只好加到0行0列 超过5个就不动了,和设置maxLength一样的效果 cell可以放任意对象
Text文本框处于编辑状态时,边框线会高亮而且文本框宽度和高度不能随单元格行高列宽自动调整。算了就这样吧,不弄了,谢谢你的帮助!
秋的红果实 2019-05-28
  • 打赏
  • 举报
回复
dgv里面,用cellEndEdit总可以吧,

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
    {
        string temp = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
        getTargetStr(temp,5); //我上面写的那个方法
    }
}

你非要那个固定长的效果,那个列,动态加载textbox,如下

private void Form1_Load(object sender, EventArgs e)
{
    TextBox text = new TextBox();
    text.Text = "hahha";
    text.Name = "tbx1"; //一万个,就用tbx10000
    text.TextChanged += new EventHandler(setText);

    dataGridView1.Rows[0].Cells[0].Value = text;
    dataGridView1.Controls.Add(text);

}
private void setText(object sender,EventArgs e)
{
    TextBox currText = (TextBox)sender;
    if(currText.Text.Trim()!=string.Empty)
    {
        currText.Text = getTargetStr(currText.Text.Trim(), 5);
        currText.Select(5, 0);
    }
}

我这没数据,只好加到0行0列 超过5个就不动了,和设置maxLength一样的效果 cell可以放任意对象
  • 打赏
  • 举报
回复
你在dgv里面试过么,这种方法的问题我已经回复给你了,如果你不明白我说的,你可以在dgv里试一下
秋的红果实 2019-05-28
  • 打赏
  • 举报
回复
引用 12 楼 简简单单相爱8 的回复:
大于5的操作我没有找到好办法,看我给9楼的回复,是我发现的几个问题,不知道有没有其他方法?
8#已经给你解决问题的方法了
ManBOyyy 2019-05-27
  • 打赏
  • 举报
回复
private void ValueChanged(object sender, EventArgs e)
{

if ( (sender as TextBox).Text.Length>5)//字節大於5
{
//大於5怎麼操作
}

}

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
(e.Control as TextBox).TextChanged += new EventHandler(ValueChanged);
}
秋的红果实 2019-05-27
  • 打赏
  • 举报
回复
dgv里的textBox和普通的差不多,想办法让每个textbox的textchange事件指向方法etTargetStr,由于时间的关系,你自己搜索下吧
秋的红果实 2019-05-27
  • 打赏
  • 举报
回复

private string getTargetStr(string input,int maxLen)
{
    string output = string.Empty;
    int num = 0;
    for (int i = 0; i < input.Length; i++)
    {
        if ((int)input[i] >= 0x4E00 && (int)input[i] <= 0x9fa5)
        {
            num += 2;
        }
        else
        {
            num++;
        }

        if (num <= maxLen)
        {
            output += input[i];
        }
        else
        {
            break;
        }

    }

    return output;

}

//textbox1_textChange里
textBox1.Text = getTargetStr(textBox3.Text.Trim(),5);
textBox1.Select(5, 0);

  • 打赏
  • 举报
回复
引用 10 楼 ManBOyyy的回复:
private void ValueChanged(object sender, EventArgs e)
{

if ( (sender as TextBox).Text.Length>5)//字節大於5
{
//大於5怎麼操作
}

}

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
(e.Control as TextBox).TextChanged += new EventHandler(ValueChanged);
}
大于5的操作我没有找到好办法,看我给9楼的回复,是我发现的几个问题,不知道有没有其他方法?
  • 打赏
  • 举报
回复
大于5的操作我没有找到好办法,看我给9楼的回复,是我发现的几个问题,不知道有没有其他方法?
  • 打赏
  • 举报
回复
引用 8 楼 秋的红果实 的回复:

private string getTargetStr(string input,int maxLen)
{
string output = string.Empty;
int num = 0;
for (int i = 0; i < input.Length; i++)
{
if ((int)input[i] >= 0x4E00 && (int)input[i] <= 0x9fa5)
{
num += 2;
}
else
{
num++;
}

if (num <= maxLen)
{
output += input[i];
}
else
{
break;
}

}

return output;

}

//textbox1_textChange里
textBox1.Text = getTargetStr(textBox3.Text.Trim(),5);
textBox1.Select(5, 0);


这个方法和10楼的配合就是我现在用的,算作第一种方法吧,代码我贴下面
        public DataGridViewTextBoxEditingControl CellEdit = null;
private void dataGridView1_EditingControlShowing_1(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if ((this.dataGridView1.CurrentCellAddress.X == 0) || (this.dataGridView1.CurrentCellAddress.X == 1))//获取当前处于活动状态的单元格索引
{
CellEdit = (DataGridViewTextBoxEditingControl)e.Control;
CellEdit.SelectAll();
CellEdit.KeyPress += Cells_KeyPress; //绑定事件
}
}
private void Cells_KeyPress(object sender, KeyPressEventArgs e) //自定义事件
{
if (System.Text.Encoding.Default.GetBytes((sender as TextBox).Text).Length >= 5)
{
e.Handled = true;
}
if (e.KeyChar == '\b')
{
e.Handled = false;
}
}

这个方法的问题是:如果长度大于指定字节后,用户按键是被屏蔽了,但是不能屏蔽鼠标右键复制粘贴指令,而且按键被屏蔽的同时也无法覆盖鼠标选中的内容,比如我输入“12345”触发事件屏蔽按键,这时我用鼠标选中“23”,想用其它字符替换就不行了。

我想到的第二种方法,如下

private void dataGridView1_CellValueChanged_1(object sender, DataGridViewCellEventArgs e)
{
if (this.dataGridView1.CurrentCellAddress.X == 0)//获取当前处于活动状态的单元格索引
{
if (System.Text.Encoding.Default.GetBytes(this.dataGridView1.CurrentCell.Value.ToString()).Length > 5)
{
MessageBox.Show("仅能输入5个字节,多余数据将被舍弃。", "提示");
string txt = this.dataGridView1.CurrentCell.Value.ToString();
this.dataGridView1.CurrentCell.Value = SubstringByte(txt, 0, 5);
dataGridView1.BeginEdit(false);
TextBox tb = (TextBox)dataGridView1.EditingControl;
tb.SelectionStart = 5;//0表示定位到最前面
}

}

}
private void dataGridView1_CurrentCellDirtyStateChanged_1(object sender, EventArgs e)
{
if (dataGridView1.IsCurrentCellDirty)
{
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}

private static Encoding _encoding = System.Text.Encoding.Default;
private string SubstringByte(string text, int startIndex, int length)
{
byte[] bytes = _encoding.GetBytes(text);
return _encoding.GetString(bytes, startIndex, length);
}
这种方法的问题是:当输入超过指定字节后,触发提示窗口,点击确定后,这条指令this.dataGridView1.CurrentCell.Value = SubstringByte(txt, 0, 5);不会立即将单元格的内容转成5字节,而是在用户点击其它单元格以后才会变成截取后的内容,这也是与Textbox控件的不同之处,此方法复制粘贴也可以适用,但每次都弹出提示框,如果复制粘贴10字节文字,不用鼠标选中一起删除,就会有n多个提示框,比如我复制粘贴“123456789”执行this.dataGridView1.CurrentCell.Value = SubstringByte(txt, 0, 5)后,单元格的内容仍然是“123456789”,然后按backspace每次删除1字节(如6、7、8、9),就会还有4个提示框,我觉得交互不大好
  • 打赏
  • 举报
回复
@秋的红果实 非常感谢你的回答,代码我测试了一下,有一下几个问题1、Textbox里的内容是没有限制的,用户可以随意组合输入,只要不超过5个字节就可以,空格算一个字节。然后就是我想要dgv的代码,Textbox的代码我参照了这篇博客,里面有源工程,功能是我想要的,只是不知道怎么应用到datagridview上的datagridviewtextcolumn上,因为单元格的值属性是Value,赋值后里面的内容需要点击一下其他的地方才会变,和Textbox不太一样,附上我看到的博客地址*https://w*ww.cnbl*ogs.com/lemony/archive/2012/05/18/707474.html(去掉*)
秋的红果实 2019-05-26
  • 打赏
  • 举报
回复
if (verifiedType(tempText) == 1 && tempText.Length > 5) ==> if ( tempText.Length > 5)
秋的红果实 2019-05-26
  • 打赏
  • 举报
回复

private int verifiedType(string input)
{
    Match match = Regex.Match(input, @"^([\u4e00-\u9fa5]+)$|^([a-z0-9]+)$");
    if(match.Groups[1].Value!=string.Empty)
    {
        return 0;
    }
    else if(match.Groups[2].Value!=string.Empty)
    {
        return 1;
    }
    else
    {
        return -1;
    }

}

private void textBox3_TextChanged(object sender, EventArgs e)
{
    string tempText = textBox3.Text.Trim();
    if(verifiedType(tempText) == 0)
    {
        if (tempText.Length > 2)
        {
            textBox3.Text = tempText.Substring(0, 2);
            textBox3.Select(2, 0);

        }
       
    }
    else if(verifiedType(tempText) == 1)
    {
        if (verifiedType(tempText) == 1 && tempText.Length > 5)
        {
            textBox3.Text = tempText.Substring(0, 5);
            textBox3.Select(5, 0);

        }
    }
    else
    {
        textBox3.Text = ""; //若是字母数字+汉字,则清空

    }
    
}

  • 打赏
  • 举报
回复
@秋的红果实 与控件自身带的Maxinputlength效果一致,只是改为用字节数限制,不用长度限制,超过预设字节数后,不在向单元格中追加内容,允许复制粘贴,但是粘贴的内容超过预设字节数,则只粘贴字节以内的内容,如 预设字节是5,剪贴板内容为“一二三”,则只粘贴“一二”。
秋的红果实 2019-05-26
  • 打赏
  • 举报
回复
你想要什么样的效果?
  • 打赏
  • 举报
回复
@秋的红果实 有代码或者工程么?我现在在单元格的输入事件中判断输入的字节数,超过5个就用messagebox提示,substring截取,但是感觉不好,不是我想要的效果,又试了在按键事件超过5个用e.cancel禁止输入,但是这样我用鼠标选中之前的文本也无法用新的字符覆盖和删除了,而且复制粘贴不触发按键事件,达不到效果。
秋的红果实 2019-05-26
  • 打赏
  • 举报
回复
正则表达式验证输入,是专门做这个的

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧