- PR -

DataGridViewでの入力バイト数制限(SJIS)

投稿者投稿内容
くろねこ
会議室デビュー日: 2007/01/22
投稿数: 5
投稿日時: 2007-01-22 21:35
Windowsプログラミングでの質問です。
開発環境はVB2005ExpressEditionです。
申し訳ありませんが.NETに触れてはじめての仕事なので、.NETをあまり解っておらず、もしかしたらまったく見当違いの質問をしているかもしれません。

以下、名前空間はSystem.Windows.Formsとして書かせていただきます。
DataGridViewで編集したデータをOracleに保存するため、DataGridViewにバイト数単位での入力制限をする必要がでてきました。
掲載されていました『c# テキストボックスに全角文字バイト数制限を制御したい』
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=28690&forum=7
を参考にさせていただいて、自分なりに書いてみましたが
コード中に「MyDataGridViewTextBoxColumnのMaxByteLengthプロパティ」と示している部分の取得の方法がわからず、進めなくなりました。
DataGridViewTextBoxEditingControlから、編集中のDataGridViewTextBoxColumnを取得するにはどうしたら良いのでしょうか。

現在のコードを長いですが載せさせていただきます。
宜しくお願いします。

コード:

Imports System.Windows.Forms
Imports System.ComponentModel

Namespace CustomCtrls.Windows.Forms

#Region "MyDataGridViewTextBoxColumn"
Public Class MyDataGridViewTextBoxColumn : Inherits System.Windows.Forms.DataGridViewTextBoxColumn
Public Sub New()
Me.MaxByteLength = 65535
Dim cell As New MyDataGridViewTextBoxCell
Me.CellTemplate = cell
End Sub
Private _MaxByteLength As Integer
<Category("動作"), DefaultValue(65535), Description("コントロールに入力できるバイト数を指定します。")> _
Public Overridable Property MaxByteLength() As Integer
Get
Return Me._MaxByteLength
End Get
Set(ByVal value As Integer)
If Me._MaxByteLength <> value Then
Me._MaxByteLength = value
End If
End Set
End Property
End Class
#End Region

#Region "MyDataGridViewTextBoxCell"
Public Class MyDataGridViewTextBoxCell : Inherits System.Windows.Forms.DataGridViewTextBoxCell
Public Sub New()
End Sub
Public Overrides ReadOnly Property EditType() As System.Type
Get
Return GetType(MaxByteLengthDataGridViewTextBoxEditingControl)
End Get
End Property
End Class
#End Region

#Region "MyDataGridViewTextBoxEditingControl"
Public Class MyDataGridViewTextBoxEditingControl : Inherits System.Windows.Forms.DataGridViewTextBoxEditingControl
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Const WM_CHAR As Integer = &H102
Const WM_PASTE As Integer = &H302
Select Case m.Msg
Case WM_CHAR
Dim eKeyPress As New KeyPressEventArgs(Microsoft.VisualBasic.ChrW(m.WParam.ToInt32()))
Me.OnChar(eKeyPress)
If eKeyPress.Handled Then
Return
End If
Case WM_PASTE
If Me.MaxLength * 2 > 「MyDataGridViewTextBoxColumnのMaxByteLengthプロパティ」 Then
Me.OnPaste(New System.EventArgs())
Return
End If
End Select
MyBase.WndProc(m)
End Sub
Protected Overridable Sub OnChar(ByVal e As System.Windows.Forms.KeyPressEventArgs)
If Char.IsControl(e.KeyChar) Then
Return
End If
Dim sjisEncoding As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS")
Dim textByteCount As Integer = sjisEncoding.GetByteCount(Me.Text)
Dim inputByteCount As Integer = sjisEncoding.GetByteCount(e.KeyChar.ToString())
Dim selectedTextByteCount As Integer = sjisEncoding.GetByteCount(Me.SelectedText)
If textByteCount + inputByteCount - selectedTextByteCount > 「MyDataGridViewTextBoxColumnのMaxByteLengthプロパティ」 Then
e.Handled = True
End If
End Sub
Protected Overridable Sub OnPaste(ByVal e As System.EventArgs)
Dim clipboardText As Object = Clipboard.GetDataObject().GetData(System.Windows.Forms.DataFormats.Text)
If clipboardText Is Nothing Then
Return
End If
Dim sjisEncoding As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS")
Dim inputText As String = clipboardText.ToString()
Dim textByteCount As Integer = sjisEncoding.GetByteCount(Me.Text)
Dim inputByteCount As Integer = sjisEncoding.GetByteCount(inputText)
Dim selectedTextByteCount As Integer = sjisEncoding.GetByteCount(Me.SelectedText)
Dim remainByteCount As Integer = 「MyDataGridViewTextBoxColumnのMaxByteLengthプロパティ」 - (textByteCount - selectedTextByteCount)
If remainByteCount <= 0 Then
Return
End If
If remainByteCount >= inputByteCount Then
Me.SelectedText = inputText
Else
Me.SelectedText = inputText.Substring(0, remainByteCount)
End If
End Sub
End Class
#End Region
End Namespace



[ メッセージ編集済み 編集者: くろねこ 編集日時 2007-01-22 21:44 ]
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-01-22 22:22
最善の方法かどうかはわかりませんが、
MyDataGridViewTextBoxEditingControlにMaxByteLengthに対応するプロパティを用意して、
それをDataGridViewTextBoxCell.InitializeEditingControlをオーバーライドして、
設定するというのはどうでしょうか?
くろねこ
会議室デビュー日: 2007/01/22
投稿数: 5
投稿日時: 2007-01-22 23:00
KI様、ありがとうございます。
引用:
それをDataGridViewTextBoxCell.InitializeEditingControlをオーバーライドして、
設定するというのはどうでしょうか?


InitializeEditingControlをオーバーライドして設定するというとはどういうことでしょうか?
DataGridViewTextBoxCellとDataGridViewTextBoxEditingControlの関係がいまだにはっきりわかっていないのですが、
InitializeEditingControlの引数にDataGridViewTextBoxEditingControlの実体が渡されてるのでしょうか?

コードを以下のように修正しました
・MyDataGridViewTextBoxEditingControlにプロパティ追加
コード:
       Private _MaxByteLength As Integer

Public Overridable Property MaxByteLength() As Integer
Get
Return _MaxByteLength
End Get
Set(ByVal value As Integer)
If _MaxByteLength <> value Then
_MaxByteLength = value
End If
End Set
End Property


・MyDataGridViewTextBoxCellのInitializeEditingControlをオーバーライド
コード:
        Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As System.Windows.Forms.DataGridViewCellStyle)

MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
End Sub



[ メッセージ編集済み 編集者: くろねこ 編集日時 2007-01-22 23:01 ]

[ メッセージ編集済み 編集者: くろねこ 編集日時 2007-01-22 23:03 ]
Ahf
大ベテラン
会議室デビュー日: 2006/08/16
投稿数: 172
投稿日時: 2007-01-22 23:14
コード:
DirectCast([DataGridViewコントロール].EditingControl, MyDataGridViewTextBoxEditingControl).MaxByteLength


といった感じでキャストしてあげるとどうでしょう?

実際には自作のEditingControlクラスかDataGridViewTextBoxEditingControlクラスでキャストすることになるかと思います。

それとカスタムセルでプロパティを保存する話題については過去スレッドがありました。
DataGridViewTextBoxColumnに追加したプロパティの値が保存されない

的はずれでしたら申し訳ないです。
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-01-22 23:19
引用:

DataGridViewTextBoxCellとDataGridViewTextBoxEditingControlの関係がいまだにはっきりわかっていないのですが、
InitializeEditingControlの引数にDataGridViewTextBoxEditingControlの実体が渡されてるのでしょうか?


EditingControlはセルが編集モードに入ったときに表示される編集用のコントロールです。
InitializeEditingControlはその初期化を行います。
InitializeEditingControlメソッドをオーバーライドする例は、下記を参照してください。

http://msdn2.microsoft.com/ja-jp/library/7tas5c80(VS.80).aspx

このメソッドをオーバーライドすることで、
EditingControlの初期化をカスタマイズできるので、
そこでMaxByteLengthを設定するという意味で言いました。
この例にあるように、DataGirdView.EditingControlをキャストして、
そのMaxByteLengthプロパティを設定すれば上手くいくと思います。
(未確認で申し訳ないですが)
くろねこ
会議室デビュー日: 2007/01/22
投稿数: 5
投稿日時: 2007-01-22 23:30
Ahfさん、KIさん、ありがとうございます。
引用:


コード:
DirectCast([DataGridViewコントロール].EditingControl, MyDataGridViewTextBoxEditingControl).MaxByteLength


といった感じでキャストしてあげるとどうでしょう?

実際には自作のEditingControlクラスかDataGridViewTextBoxEditingControlクラスでキャストすることになるかと思います。


引用:

この例にあるように、DataGirdView.EditingControlをキャストして、
そのMaxByteLengthプロパティを設定すれば上手くいくと思います。



とのことですが、非常に勘違いな質問かも知れないのですが、
サンプルでは
コード:
Dim ctl As CalendarEditingControl = _
            CType(DataGridView.EditingControl, CalendarEditingControl)
        ctl.Value = CType(Me.Value, DateTime)


となっていて、
コード:
DirectCast([DataGridViewコントロール].EditingControl, MyDataGridViewTextBoxEditingControl).MaxByteLength


とよく似ているのですが、
サンプルのほうは CalendarEditingControl 型のctl変数?に値を代入しているだけのように
見えるのですが、これでプロパティを設定したことになっているのでしょうか?
自分自身よくわかっていないので、よくわからない質問になってスミマセン。
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-01-22 23:39
引用:

サンプルのほうは CalendarEditingControl 型のctl変数?に値を代入しているだけのように
見えるのですが、これでプロパティを設定したことになっているのでしょうか?
自分自身よくわかっていないので、よくわからない質問になってスミマセン。


クラスは参照型ですから、ctlという変数には参照が代入されるだけですので、

コード:

CType(DataGridView.EditingControl, CalendarEditingControl).Value = CType(Me.Value, DateTime)



と書いたのと同じことになります。
値型と参照型の違いを意識してください。

参考
http://www.microsoft.com/japan/msdn/net/vbnetref/vbnetref3-2.aspx
くろねこ
会議室デビュー日: 2007/01/22
投稿数: 5
投稿日時: 2007-01-23 00:06
KIさんありがとうございます。
引用:

クラスは参照型ですから、ctlという変数には参照が代入されるだけですので、

コード:


CType(DataGridView.EditingControl, CalendarEditingControl).Value = CType(Me.Value, DateTime)



と書いたのと同じことになります。
値型と参照型の違いを意識してください。

参考
http://www.microsoft.com/japan/msdn/net/vbnetref/vbnetref3-2.aspx


よくわかりました。

コード:
        Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As System.Windows.Forms.DataGridViewCellStyle)

MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
Dim ctl As MyDataGridViewTextBoxEditingControl
ctl = CType(DataGridView.EditingControl, MyDataGridViewTextBoxEditingControl)
ctl.MaxByteLength = Me.OwningColumn.MaxByteLength
End Sub


と修正しましたが、Me.OwningColumn.MaxByteLengthのところで
"MaxByteLengthはDataGridViewTextBoxColumnのメンバではありません"
とのエラーが出ました。(当然かと思いますが)
コード:

ctl.MaxByteLength = DirectCast(Me.OwningColumn, MaxByteLengthDataGridViewTextBoxColumn).MaxByteLength


と、強制的にキャストしてしまっても良いのでしょうか?
(領域破壊にならないでしょうか?)



[ メッセージ編集済み 編集者: くろねこ 編集日時 2007-01-23 00:12 ]

スキルアップ/キャリアアップ(JOB@IT)