WPF TextBox實(shí)現(xiàn)按字節(jié)長(zhǎng)度限制輸入功能
前兩天做一個(gè)項(xiàng)目的時(shí)候,由于頁(yè)面沒(méi)有限制TextBox的輸入長(zhǎng)度,所以,后臺(tái)直接報(bào)錯(cuò)了,超出數(shù)據(jù)庫(kù)最大的長(zhǎng)度。
數(shù)據(jù)庫(kù)的長(zhǎng)度是按照字節(jié)來(lái)計(jì)算的,而且不同的編碼格式,漢字占用的字節(jié)長(zhǎng)度又不相同,比如,我們用的是UTF8,一個(gè)漢字是3個(gè)字節(jié),而默認(rèn)的Default,一個(gè)漢字是2個(gè)字節(jié)。
TextBox有個(gè)MaxLength屬性,但是這個(gè)屬性是不太合乎要求的,因?yàn)檫@個(gè)長(zhǎng)度,是限制了輸入的長(zhǎng)度,比如設(shè)置20,則無(wú)論是數(shù)字、字母、漢字最大的長(zhǎng)度都是20個(gè),但是,對(duì)于數(shù)據(jù)庫(kù)來(lái)說(shuō),長(zhǎng)度卻不相同了,所以,不能使用這個(gè)屬性。
為了,統(tǒng)一解決下這個(gè)問(wèn)題,所以給TextBox寫了附加屬性。
一、想要的效果
用了附加屬性,想達(dá)到一個(gè)什么效果呢,就是像設(shè)置MaxLength一樣,一旦到了數(shù)據(jù)庫(kù)的字節(jié)長(zhǎng)度,就不再能輸入了。
因此,最開始想找一個(gè)限制輸入的屬性,可惜我學(xué)的太淺薄,沒(méi)有找到相關(guān)的屬性,因此,最后在同事的提醒下,可以記錄上一次的內(nèi)容,然后,如果超長(zhǎng),就用上一次的內(nèi)容進(jìn)行賦值
二、附加屬性
既然要用附加屬性,并且方便使用,那肯定要給開發(fā)者暴露出來(lái)至少兩個(gè):MaxByteLength用來(lái)設(shè)置最大的字節(jié)數(shù),EncodeModel用來(lái)設(shè)置編碼格式
EncodeModel是用Menu類型來(lái)做的,方便使用時(shí)直接敲內(nèi)容
本來(lái)上面是直接想用Encoding來(lái)做的,奈何它是抽象類,只好,寫個(gè)方法進(jìn)行了一部轉(zhuǎn)化,并且把Encoding類型的屬性進(jìn)行private。
大致上也就是這么一個(gè)思路,下面上代碼,給需要的人使用。
public class MaxByteAttachedProperty : DependencyObject { public enum Encode { Default, ASCII, UTF8, UTF32, UTF7, BigEndianUnicode, Unicode } private static string GetPreText(DependencyObject obj) { return (string)obj.GetValue(PreTextProperty); } private static void SetPreText(DependencyObject obj, string value) { obj.SetValue(PreTextProperty, value); } // Using a DependencyProperty as the backing store for PreText. This enables animation, styling, binding, etc... private static readonly DependencyProperty PreTextProperty = DependencyProperty.RegisterAttached("PreText", typeof(string), typeof(MaxByteAttachedProperty), new PropertyMetadata("")); public static int GetMaxByteLength(DependencyObject obj) { return (int)obj.GetValue(MaxByteLengthProperty); } public static void SetMaxByteLength(DependencyObject obj, int value) { obj.SetValue(MaxByteLengthProperty, value); } // Using a DependencyProperty as the backing store for MaxByteLength. This enables animation, styling, binding, etc... public static readonly DependencyProperty MaxByteLengthProperty = DependencyProperty.RegisterAttached("MaxByteLength", typeof(int), typeof(MaxByteAttachedProperty), new PropertyMetadata(OnTextBoxPropertyChanged)); private static void OnTextBoxPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBox tb = d as TextBox; if (tb == null) { return; } tb.TextChanged += Tb_TextChanged; } private static void Tb_TextChanged(object sender, TextChangedEventArgs e) { TextBox tb = sender as TextBox; if (IsOutMaxByteLength(tb.Text, tb)) { tb.Text = GetPreText(tb); tb.Select(tb.Text.Length, 0); return; } } public static Encode GetEncodeModel(DependencyObject obj) { return (Encode)obj.GetValue(EncodeModelProperty); } public static void SetEncodeModel(DependencyObject obj, Encode value) { obj.SetValue(EncodeModelProperty, value); } // Using a DependencyProperty as the backing store for EncodeM. This enables animation, styling, binding, etc... public static readonly DependencyProperty EncodeModelProperty = DependencyProperty.RegisterAttached("EncodeModel", typeof(Encode), typeof(MaxByteAttachedProperty), new PropertyMetadata(Encode.UTF8, OnEncodeModelChanged)); private static void OnEncodeModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { SetEM(d, GetEncodeModel(d)); } private static Encoding GetEncodingModel(DependencyObject obj) { return (Encoding)obj.GetValue(EncodingModelProperty); } private static void SetEncodingModel(DependencyObject obj, Encoding value) { obj.SetValue(EncodingModelProperty, value); } // Using a DependencyProperty as the backing store for EncodingModel. This enables animation, styling, binding, etc... private static readonly DependencyProperty EncodingModelProperty = DependencyProperty.RegisterAttached("EncodingModel", typeof(Encoding), typeof(MaxByteAttachedProperty), new PropertyMetadata(Encoding.UTF8)); private static void SetEM(DependencyObject obj, Encode e) { switch (e) { case Encode.Default: SetEncodingModel(obj, Encoding.Default); break; case Encode.ASCII: SetEncodingModel(obj, Encoding.ASCII); break; case Encode.UTF8: SetEncodingModel(obj, Encoding.UTF8); break; case Encode.UTF32: SetEncodingModel(obj, Encoding.UTF32); break; case Encode.UTF7: SetEncodingModel(obj, Encoding.UTF7); break; case Encode.BigEndianUnicode: SetEncodingModel(obj, Encoding.BigEndianUnicode); break; case Encode.Unicode: SetEncodingModel(obj, Encoding.Unicode); break; default: break; } } private static bool IsOutMaxByteLength(string txt, DependencyObject obj) { int txtLength = GetEncodingModel(obj).GetBytes(txt).Length;//文本長(zhǎng)度 if (GetMaxByteLength(obj) >= txtLength) { SetPreText(obj, txt); return false; } return true; } }
使用方法如下:
MaxByteLength是必須設(shè)置的沒(méi)有進(jìn)行默認(rèn),EncodeModel可以不設(shè)置但是由于是我們自己用,所以默認(rèn)是UTF8,可以自行修改代碼,按照你們公司的編碼格式,這樣也就不用賦值了。
代碼已修正,感謝Presia發(fā)現(xiàn)的BUG,疏忽了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#實(shí)現(xiàn)將聊天數(shù)據(jù)發(fā)送加密
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)將聊天數(shù)據(jù)發(fā)送加密的功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12C#采用Winform實(shí)現(xiàn)類似Android的Listener
這篇文章主要介紹了C#采用Winform實(shí)現(xiàn)類似Android的Listener,很實(shí)用的技巧,需要的朋友可以參考下2014-08-08C#中Request.Cookies 和 Response.Cookies 的區(qū)別分析
本文通過(guò)實(shí)例代碼向我們展示了C#中Request.Cookies 和 Response.Cookies 的區(qū)別,文章淺顯易懂,這里推薦給大家。2014-11-11C#向線程中傳遞多個(gè)參數(shù)的解決方法(兩種)
這篇文章主要介紹了C#向線程中傳遞多個(gè)參數(shù)的解決方法(兩種)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07C#預(yù)定義數(shù)據(jù)類型之值類型和引用類型介紹
這篇文章主要介紹了C#預(yù)定義數(shù)據(jù)類型之值類型和引用類型介紹,本文著重講解了引用類型中的object(對(duì)象)類型和string(字符串)類型,需要的朋友可以參考下2015-03-03通過(guò)容器擴(kuò)展屬性IExtenderProvider實(shí)現(xiàn)WinForm通用數(shù)據(jù)驗(yàn)證組件
這篇文章介紹了通過(guò)容器擴(kuò)展屬性IExtenderProvider實(shí)現(xiàn)WinForm通用數(shù)據(jù)驗(yàn)證組件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12