3

DataGridViewにオブジェクトのリストを表示する Windows フォーム アプリがあります。

このコントロールは、bool 値をチェックボックスとしてレンダリングします。

オブジェクト プロパティには、相互に排他的な 3 つのチェック ボックスのセットがあります。多くても、そのうちの 1 つが true になる可能性があります。したがって、チェックボックスを一連のラジオ ボタンのように機能させたいと考えています。

老人からのちょっとしたコメント: 最近の人は、なぜこれらがラジオ ボタンと呼ばれているのかさえ知らないと思います。昔、車のラジオには 4 つまたは 5 つのボタンがあり、そのうちの 1 つを押すと他のすべてのボタンが飛び出しました。それらは相互に排他的でした。「ラジオ ボタン」という説明は、最近ではおそらく役に立たないでしょう。なぜなら、ラジオにはそのようなボタンがもうないからだと思います。

どうすればいいですか?チェックボックスに「CheckedChanged」イベントを添付すると、行がわかっているので、他のすべてのチェックボックスを見つけることができます。

CheckedChanged イベントをアタッチできるように、チェックボックス コントロールが最初にレンダリングされたときにそれを取得するためにフックできるイベントは何ですか? については知ってDataGridView.CellFormattingいますが、DataGridView が描画されるたびに呼び出されるため、それは間違っていると思います。DGV が初めてレンダリングされるときにのみ呼び出されるイベントが本当に必要です。

4

4 に答える 4

7

役立つ回答をくれた KeithS に感謝します。

CellValueChangedのドキュメントを調べたところ、次のような役立つ情報が見つかりました。

DataGridView.CellValueChanged イベントは、ユーザー指定の値がコミットされたときに発生します。これは通常、フォーカスがセルから離れたときに発生します。

ただし、チェック ボックス セルの場合は、通常、変更をすぐに処理する必要があります。セルがクリックされたときに変更をコミットするには、DataGridView.CurrentCellDirtyStateChanged イベントを処理する必要があります。ハンドラーで、現在のセルがチェック ボックス セルの場合は、DataGridView.CommitEdit メソッドを呼び出して、Commit 値を渡します。

これは、ラジオの動作を取得するために使用したコードです。

    void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        // Manually raise the CellValueChanged event
        // by calling the CommitEdit method.
        if (dataGridView1.IsCurrentCellDirty)
        {
            dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }

    public void dataGridView1_CellValueChanged(object sender,
                                               DataGridViewCellEventArgs e)
    {
        // If a check box cell is clicked, this event handler sets the value
        // of a few other checkboxes in the same row as the clicked cell.
        if (e.RowIndex < 0) return; // row is sometimes negative?
        int ix = e.ColumnIndex;
        if (ix>=1 && ix<=3)
        {
            var row = dataGridView1.Rows[e.RowIndex];

            DataGridViewCheckBoxCell checkCell =
                (DataGridViewCheckBoxCell) row.Cells[ix];

            bool isChecked = (Boolean)checkCell.Value;
            if (isChecked)
            {
                // Only turn off other checkboxes if this one is ON. 
                // It's ok for all of them to be OFF simultaneously.
                for (int i=1; i <= 3; i++)
                {
                    if (i != ix)
                    {
                        ((DataGridViewCheckBoxCell) row.Cells[i]).Value = false;
                    }
                }
            }
            dataGridView1.Invalidate();
        }
    }
于 2012-05-03T20:56:32.137 に答える
1
  private void dataGridViewProduit_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        if ((sender as DataGridView).CurrentCell is DataGridViewCheckBoxCell)
        {
            if (Convert.ToBoolean(((sender as DataGridView).CurrentCell as DataGridViewCheckBoxCell).Value))
            {
                foreach (DataGridViewRow row in (sender as DataGridView).Rows)
                {
                    if (row.Index != (sender as DataGridView).CurrentCell.RowIndex && Convert.ToBoolean(row.Cells[e.ColumnIndex].Value) == true)
                    {
                        row.Cells[e.ColumnIndex].Value = false;
                    }
                }
            }
        }
    }

    private void dataGridViewClient_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        if (this.dataGridViewClient.IsCurrentCellDirty)
        {
            dataGridViewClient.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }
于 2013-08-08T23:39:56.170 に答える
1

必要なのは、DGV 自体の CellContentClick です。DGV のその列が CheckBoxCell であるかどうかをチェックするハンドラーをアタッチし、そうである場合は、行の他のすべてのチェックボックスをオフにします。

ただし、CheckBoxCell の場合、このイベントはチェックボックスの値が実際に変更される前に発生します。これは、現在のセルに対して何を行っても、後で発生するイベントによって上書きされることを意味します。これから揺れ動く動作は、行の1つのボックスをチェックしてからもう一度チェックすることで、行のセルをどれもチェックできないということです(ハンドラーでチェックボックスの値を設定しようとするかどうかにかかわらず、チェックボックスは、2 回目のクリック後にクリアされます)。それを克服し、チェックボックスの1つを強制的にチェックするには、代わりにCellValueChangedを処理し、変更されたセルが現在のセルでチェックされていない場合はチェックします。

于 2012-05-03T20:18:21.053 に答える
0

ここでは簡単すぎるでしょう:

チェックボックスの列は、datagridview の 2 番目の列であると考えてください。

private void YourDatagridview_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
         if (IsHandleCreated)
        {
            if (YourDatagridview.CurrentCell == YourDatagridview.Rows[e.RowIndex].Cells[1])
            {
                if (Convert.ToBoolean(YourDatagridview.CurrentCell.Value) == true)
                {
                    for (int i = 0; i < YourDatagridview.RowCount; i++)
                    {
                        if (YourDatagridview.Rows[i].Cells[1] != YourDatagridview.CurrentCell)
                        {
                            YourDatagridview.Rows[i].Cells[1].Value = false;
                        }
                    }
                }
            }
        }
    }

そして、これも呼び出します:

private void YourDatagridview_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        if (this.YourDatagridview.IsCurrentCellDirty)
        {
            YourDatagridview.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }

そして出来上がり!

于 2015-11-05T06:27:33.113 に答える