melt日記

.NETすらまともに扱えないへたれのページ

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  111  : 記事  3  : コメント  8268  : トラックバック  41

ニュース

わんくま同盟

わんくま同盟

C# と VB.NET の質問掲示板

iKnow!


Dictation



書庫

NCName に使用可能な文字しか入力出来ない TextBox を作ろうと思っていろいろ調べてみました。

 

特定の文字しか入力出来ないようにするには、じゃんぬさんの数字または一部の文字しか入力できないようにするのソースを改造すればいけそうです。

ある文字列が NCName かどうかを判断するには System.Xml.XmlConvert.VerifyNCName() を使えば可能です。

VerifyNCName() は、与えられた文字列が NCName でなかった場合は例外を投げます。

 

この2つを使えば実装することが出来そうです。

ただし、NCName は1文字目と2文字目以降で使用できる文字が違うので注意する必要があります。

こんな感じになります(変更したところだけ抜粋)。

#region OnChar メソッド (virtual)
 
protected virtual void OnChar(KeyPressEventArgs e)
{
    if (char.IsControl(e.KeyChar))
    {
        return;
    }
 
    if (!HasPermitChars(e.KeyChar, this.SelectionStart))
    {
        e.Handled = true;
    }
}
 
#endregion
 
#region OnPaste メソッド (virtual)
 
protected virtual void OnPaste(System.EventArgs e)
{
    string stString = Clipboard.GetDataObject().GetData(DataFormats.Text).ToString();
 
    if (stString != null)
    {
        this.SelectedText = GetPermitedString(stString, this.SelectionStart);
    }
}
 
#endregion
 
#region HasPermitChars メソッド
 
private bool HasPermitChars(char chTarget, int index)
{
    if (index == 0)
    {
        return IsStartNCNameChar(chTarget);
    }
    else
    {
        return IsNCNameChar(chTarget);
    }
}
 
#endregion
 
#region GetPermitedString メソッド
 
private string GetPermitedString(string stTarget, int index)
{
    string stReturn = string.Empty;
 
    foreach (char chTarget in stTarget)
    {
        if (HasPermitChars(chTarget, index))
        {
            stReturn += chTarget;
            index++;
        }
    }
 
    return stReturn;
}
 
#endregion
 
// NCName の1文字目として正しい文字かどうかを検証する
public bool IsStartNCNameChar(char ch)
{
    try
    {
        XmlConvert.VerifyNCName(ch.ToString());
        return true;
    }
    catch (XmlException e)
    {
        return false;
    }
}
// NCName の2文字目以降として正しい文字かどうかを検証する
public bool IsNCNameChar(char ch)
{
    try
    {
        // 2文字目以降の検証なので、
        // 1文字目にに正しい NCName 文字を入れてやる
        XmlConvert.VerifyNCName("a" + ch.ToString());
        return true;
    }
    catch (XmlException e)
    {
        return false;
    }
}

一応これで完成になるのですが、ある文字が NCName かどうか何てちょっとした if 文を書けば終わりじゃないの?と思っている自分にとっては IsStartNCNameChar() と IsNCNameChar() で例外を投げまくってたり、IsNCNameChar() で文字列の連結したりといった無駄な処理をしているのが非常に気になります。

 

ということで、もっとカッコイイ実装方法は無いかといろいろ調べてみました。

 

結果、.NET Framework では文字を検証するためのフラグを 65536 個全ての文字に対してテーブルとして持っていて、ある文字が NCName かどうかをフラグが立っているかどうかで判断しているようです。

そして、そのテーブルは System.Xml アセンブリのリソースに XmlCharType.bin という名前で置いてあります。

これを使えばもっとスマートに書くことが出来そうです。

private static readonly byte[] s_charProperties;
 
#region コンストラクタ
 
public NCNameTextBox()
{
    if (s_charProperties == null)
    {
        Stream stream =
            Assembly.GetAssembly(typeof(XmlElement)).GetManifestResourceStream("XmlCharType.bin");
        byte[] v = new byte[stream.Length];
        stream.Read(v, 0, v.Length);
 
        s_charProperties = v;
    }
}
 
#endregion
 
...
 
public bool IsStartNCNameChar(char ch)
{
    // NCName の1文字目で使用できる文字だった場合は
    // このビットが立っている
    return (s_charProperties[ch] & 4) != 0;
}
public bool IsNCNameChar(char ch)
{
    // NCName の2文字目以降で使用できる文字だった場合は
    // このビットが立っている
    return (s_charProperties[ch] & 8) != 0;
}

これですっきりしました。

ただ、これは unofficial な方法なので、今後の .NET Framework で動くかどうかは定かではありません。

投稿日時 : 2007年9月30日 14:34

コメント

# re: [C#]有効な NCName 以外の文字を削除する方法 2007/09/30 15:58 渋木宏明(ひどり)
悩ましいですね>1文字チェックごとに例外の可能性

駄目元で、「TryParse みたいに例外を投げないチェックメソッドを追加汁」とフィードバックしてみるとか。


# re: [C#]有効な NCName 以外の文字を削除する方法 2007/10/01 18:16 melt
フィードバックの方法が分かりません……o…rz

# FOlPbowOLzXzkqrdNJr 2011/12/12 19:20 http://www.d4women.net/clomid.php
I serched through the internet and got here. What a wonderful invention of the mankind. With the help of the network you communicate, learn, read !... That helped us to get acquainted!...

# ItemMsJfiYIaXrvTng 2011/12/16 0:55 http://www.yacanna.com/
Not bad post, but a lot of extra !!...

# pDOJjpiauDKNtS 2011/12/17 19:52 http://www.coursbatterie.com
Heartfelt thanks..!

# KZyHGqEjKvwdXAgjC 2012/01/04 5:12 http://www.kosherbeefjerky.net/
wwThUB Pleased to read intelligent thoughts in Russian. I`ve been living in England for already 5 years!...

Post Feedback

タイトル
名前
Url:
コメント