【问题标题】:How to limit textbox maxlength by byte in winrt?如何在winrt中按字节限制文本框最大长度?
【发布时间】:2013-12-20 09:42:03
【问题描述】:

对于TextBox,有一个属性“MaxLength”,但它把所有的ascii和unicode都算作1个字符。
但是在数据库中,我们设置了字段 varchar(n) 。它处理 ascii 1 和 unicode 2。

如何按字节限制文本框输入?

因为在文本更改之前没有通知,所以解决方法如下。

public class TextBoxEx : TextBox
    {
    private bool bIsChanging;

    public TextBoxEx()
    {
        TextChanged += TextBoxEx_TextChanged;
    }

    public int MaxByteLength { private get; set; }

    private void TextBoxEx_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (bIsChanging || MaxByteLength == 0 || Text.Length*2 <= MaxByteLength)
            return;
        bIsChanging = true;
        int start = SelectionStart;
        Text = TruncateString(Text, MaxByteLength);
        SetLimit();
        SelectionStart = start;
        bIsChanging = false;
    }

    private void SetLimit()
    {
        MaxLength = MaxByteLength - Encoding.UTF8.GetBytes(Text).Length + Text.Length;
    }

    private static string TruncateString(string text, int max)
    {
        if (max == 0) return text;
        byte[] bytes = Encoding.UTF8.GetBytes(text);
        if (bytes.Length <= max) return text;
        char[] c = text.ToCharArray();
        var sb = new StringBuilder();
        int count = 0;
        foreach (char t in c)
        {
            count += Encoding.UTF8.GetByteCount(t.ToString());
            if (max >= count)
            {
                sb.Append(t);
            }
            else
            {
                break;
            }
        }
        return sb.ToString();
    }
}

【问题讨论】:

  • TextBox 的内部缓冲区采用 16 位代码单元,因此就 TextBox 而言,“ascii”字符仍占用 2 个字节,因此即使您可以告诉 TextBox 改为计算字节数这不会做你想要的。您必须编写代码来查看 TextBox 拥有的数据并计算数据库将使用多少字节来存储该数据。另外,您确定数据库对所有字符只使用一两个字节吗?如果数据库将数据存储为 UTF-8,则 Unicode 字符可以是一个、两个、三个或四个字节。

标签: c# sql unicode windows-runtime winrt-xaml


【解决方案1】:

ascii码也是16进制,1个字符代表2个字节的信息

EX: "A" 是 41(Hx) 0100 0001 即 2 个字节,以此类推

【讨论】:

    【解决方案2】:

    我觉得你应该参考this answer

    建议您自己处理(在这种情况下,它限制 12 个字节的长度):

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        var textBytes = Encoding.UTF8.GetBytes(textBox1.Text);
        var textByteCount = Encoding.UTF8.GetByteCount(textBox1.Text);
        var textCharCount = Encoding.UTF8.GetCharCount(textBytes);
    
        if (textCharCount != textByteCount && textByteCount >= 12)
        {
            textBox1.Text = Encoding.UTF32.GetString(Encoding.UTF32.GetBytes(textBox1.Text), 0, 12);
        }
        else if (textBox1.Text.Length >= 6)
        {
            textBox1.Text = textBox1.Text.Substring(0, 6);
        }
    }  
    

    【讨论】:

    • 我会避免使用子字符串,而是恢复到以前的值。为了允许粘贴更长的字符串或使用允许插入整个单词的屏幕键盘 - 我将保存以前的 Text 和以前的 SelectionStart+SelectionLength 以确定在文本更改时要剪辑的内容。
    【解决方案3】:

    我会简单地使用 MaxLength 的一半 varchar(n) 中的 n

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-19
      • 2010-12-28
      • 2013-10-02
      • 1970-01-01
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多