EditingControl.TextChangedイベントの発生回数を制御する方法

文書番号 : 40505     文書種別 : 使用方法     登録日 : 2017/07/26     最終更新日 : 2017/07/26
文書を印刷する
対象製品
MultiRow for Windows Forms 10.0J
詳細
DataGridViewコントロールとGcMultiRowコントロールでそれぞれセル編集コントロール(EditingControl)のTextChangedイベントを実装したとき、イベントの発生回数が異なります。これは、GcMultiRowコントロールがセル移動時にセル編集コントロールの編集開始位置が常に適正になるように、内部で一度EditingControl.Textプロパティを初期化していることによるものです。

次のコードは、この現象を確認します。

[Visual Basic]
Imports GrapeCity.Win.MultiRow

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    DataGridView1.RowCount = 10
    For i As Integer = 0 To DataGridView1.RowCount - 1
        DataGridView1.Rows(i).Cells(0).Value = i
    Next

    Dim textBoxCell = New TextBoxCell()
    textBoxCell.Name = "textBoxCell"
    GcMultiRow1.Template = Template.CreateGridTemplate(New Cell() {textBoxCell})
    GcMultiRow1.RowCount = 10
    For i As Integer = 0 To GcMultiRow1.RowCount - 1
        GcMultiRow1.SetValue(i, "textBoxCell", i)
    Next
End Sub

Private Sub DataGridView1_EditingControlShowing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
   If TypeOf DataGridView1.CurrentCell Is DataGridViewTextBoxCell Then
       Dim textBox As DataGridViewTextBoxEditingControl = TryCast(e.Control, DataGridViewTextBoxEditingControl)
       RemoveHandler textBox.TextChanged, AddressOf dataGridView_textBox_TextChanged
        AddHandler textBox.TextChanged, AddressOf dataGridView_textBox_TextChanged
    End If
End Sub

Private Sub dataGridView_textBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs)
    Dim textBox As DataGridViewTextBoxEditingControl = TryCast(sender, DataGridViewTextBoxEditingControl)
    Console.WriteLine("DataGridView_textBox_TextChanged:{0}", textBox.Text)
End Sub

Private Sub GcMultiRow1_EditingControlShowing(ByVal sender As System.Object, ByVal e As GrapeCity.Win.MultiRow.EditingControlShowingEventArgs) Handles GcMultiRow1.EditingControlShowing
   If TypeOf GcMultiRow1.CurrentCell Is TextBoxCell Then
       Dim textBox As TextBoxEditingControl = TryCast(e.Control, TextBoxEditingControl)
        RemoveHandler textBox.TextChanged, AddressOf gcMultiRow_textBox_TextChanged
        AddHandler textBox.TextChanged, AddressOf gcMultiRow_textBox_TextChanged
    End If
End Sub

Private Sub gcMultiRow_textBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs)
    Dim textBox As TextBoxEditingControl = TryCast(sender, TextBoxEditingControl)
    Console.WriteLine("GcMultiRow_textBox_TextChanged:{0}", textBox.Text)
End Sub

[C#]
using GrapeCity.Win.MultiRow;

private void Form1_Load(object sender, EventArgs e)
{
    dataGridView1.RowCount = 10;
    for (int i = 0; i < dataGridView1.RowCount; i++)
    {
        dataGridView1.Rows[i].Cells[0].Value = i;
    }
    dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);
    
    TextBoxCell textBoxCell = new TextBoxCell();
    textBoxCell.Name = "textBoxCell";
    
    gcMultiRow1.Template = Template.CreateGridTemplate(new Cell[] { textBoxCell });
    gcMultiRow1.RowCount = 10;
    
    for (int i = 0; i < gcMultiRow1.RowCount; i++)
    {
        gcMultiRow1.SetValue(i, "textBoxCell", i);
    }
    gcMultiRow1.EditingControlShowing += new EventHandler<GrapeCity.Win.MultiRow.EditingControlShowingEventArgs>(gcMultiRow1_EditingControlShowing);
}

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    if (dataGridView1.CurrentCell is DataGridViewTextBoxCell)
    {
        DataGridViewTextBoxEditingControl textBox = e.Control as DataGridViewTextBoxEditingControl;
        textBox.TextChanged -= new EventHandler(dataGridView_textBox_TextChanged);
        textBox.TextChanged += new EventHandler(dataGridView_textBox_TextChanged);
    }
}

private void dataGridView_textBox_TextChanged(object sender, EventArgs e)
{
    DataGridViewTextBoxEditingControl textBox = sender as DataGridViewTextBoxEditingControl;
    Console.WriteLine("DataGridView_textBox_TextChanged:{0}", textBox.Text);
}

private void gcMultiRow1_EditingControlShowing(object sender, EditingControlShowingEventArgs e)
{
    if (gcMultiRow1.CurrentCell is TextBoxCell)
    {
        TextBoxEditingControl textBox = e.Control as TextBoxEditingControl;
        textBox.TextChanged -= new EventHandler(gcMultiRow_textBox_TextChanged);
        textBox.TextChanged += new EventHandler(gcMultiRow_textBox_TextChanged);
    }
}

private void gcMultiRow_textBox_TextChanged(object sender, EventArgs e)
{
    TextBoxEditingControl textBox = sender as TextBoxEditingControl;
    Console.WriteLine("GcMultiRow_textBox_TextChanged:{0}", textBox.Text);
}

この現象を回避し、DataGridViewと同じ回数だけEditingControl.TextChangedイベントを発生させるには、次のようにコードを書き換えます。

[Visual Basic]
Private editingControlRemoving As Boolean = False

Private Sub GcMultiRow1_ControlRemoved(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ControlEventArgs) Handles GcMultiRow1.ControlRemoved
    If e.Control Is GcMultiRow1.EditingPanel Then
        editingControlRemoving = True
        GcMultiRow1.EditingControl.Text = String.Empty
        editingControlRemoving = False
    End If
End Sub

Private Sub gcMultiRow_textBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs)
    Dim textBox As TextBoxEditingControl = TryCast(sender, TextBoxEditingControl)
    If Not editingControlRemoving Then
        Console.WriteLine("GcMultiRow_textBox_TextChanged:{0}", textBox.Text)
    End If
End Sub

[C#]
private void Form1_Load(object sender, EventArgs e)
{
    ...
    // 以下のコードを追加
    gcMultiRow1.ControlRemoved += new ControlEventHandler(gcMultiRow1_ControlRemoved);
}

bool editingControlRemoving = false;

private void gcMultiRow1_ControlRemoved(object sender, ControlEventArgs e)
{
    if (e.Control == gcMultiRow1.EditingPanel)
    {
        editingControlRemoving = true;
        gcMultiRow1.EditingControl.Text = string.Empty;
        editingControlRemoving = false;
    }
}

private void gcMultiRow_textBox_TextChanged(object sender, EventArgs e)
{
    TextBoxEditingControl textBox = sender as TextBoxEditingControl;

    if (!editingControlRemoving)
    {
        Console.WriteLine("gcMultiRow_textBox_TextChanged:{0}", textBox.Text);
    }
}

セルの移動時にEditingControl.TextChangedイベントを発生させず、ユーザーによる編集が行われた場合のみEditingControl.TextChangedイベントを発生させるには、次のように書き換えます。

[Visual Basic]
Private _currentCellPosition As CellPosition = CellPosition.Empty

Private Sub GcMultiRow1_EditingControlShowing(ByVal sender As System.Object, ByVal e As GrapeCity.Win.MultiRow.EditingControlShowingEventArgs) Handles GcMultiRow1.EditingControlShowing
    If TypeOf GcMultiRow1.CurrentCell Is TextBoxCell Then
        _currentCellPosition = GcMultiRow1.CurrentCellPosition
        Dim textBox As TextBoxEditingControl = TryCast(e.Control, TextBoxEditingControl)
        RemoveHandler textBox.TextChanged, AddressOf gcMultiRow_textBox_TextChanged
        AddHandler textBox.TextChanged, AddressOf gcMultiRow_textBox_TextChanged
    End If
End Sub

Private Sub gcMultiRow_textBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs)
    Dim textBox As TextBoxEditingControl = TryCast(sender, TextBoxEditingControl)
    If textBox.GcMultiRow.CurrentCellPosition.Equals(_currentCellPosition) Then
        Console.WriteLine("GcMultiRow_textBox_TextChanged:{0}", textBox.Text)
    End If
End Sub

[C#]
private CellPosition _currentCellPosition = CellPosition.Empty;

private void gcMultiRow1_EditingControlShowing(object sender, EditingControlShowingEventArgs e)
{
    if (gcMultiRow1.CurrentCell is TextBoxCell)
    {
        _currentCellPosition = gcMultiRow1.CurrentCellPosition;
        TextBoxEditingControl textBox = e.Control as TextBoxEditingControl;
        textBox.TextChanged -= new EventHandler(gcMultiRow_textBox_TextChanged);
        textBox.TextChanged += new EventHandler(gcMultiRow_textBox_TextChanged);
    }
}

private void gcMultiRow_textBox_TextChanged(object sender, EventArgs e)
{
    TextBoxEditingControl textBox = sender as TextBoxEditingControl;
    if (textBox.GcMultiRow.CurrentCellPosition.Equals(_currentCellPosition))
    {
        Console.WriteLine("gcMultiRow_textBox_TextChanged:{0}", textBox.Text);
    }
}

EditingControl.TextChangedイベントの代わりにGcMultiRow.CellEditedFormattedValueChangedイベントを使用することもできます。