2

2つのテキストボックス列と1つのコンボボックス列を持つdatagridviewがあります。コンボボックスのデータソースは、ドロップダウンの値の列挙型にバインドされています。datagridviewのDataSourceは、string、string、およびenumのデータ型を持つカスタムクラスにバインドされています。

最初の2列には値が事前に入力されており、3番目の列でユーザーはドロップダウンから値を選択する必要があります。これまでのところ、これはすべてうまく機能しています。

コンボボックスフィールドは1対1の種類のマッピングである必要があります。つまり、2つのコンボボックスが同じ値を持つことはできません。この種の動作を実装する方法が本当にわかりません。選択した値を残りのドロップダウンから削除する必要がありますか?選択した値をドロップダウンに残し、同じ値を2つ選択したときにエラーを表示する必要がありますか?

任意のアイデアとこれらのアイデアを実装する方法は非常に役立ちます。

ありがとう

複数回使用できる唯一の許容値は「なし」であることに注意してください

ここに画像の説明を入力してください

4

2 に答える 2

1

残りのドロップダウンから選択した値を削除する可能性があるというあなたの意図に基づいたアイデアがあります。

Runnerあなたの例と同様の設定を持つというクラスがあります。

Public Class Runner

    Public Property FirstName As String
    Public Property LastName As String
    Public Property Placement As Result

    Public Sub New(fn As String, ln As String)
        FirstName = fn
        LastName = ln
        Placement = Result.None
    End Sub

End Class

また、 :Resultに入力される列挙型があります。ComboBoxCell

Public Enum Result
    None = 0
    Bronze = 1
    Silver = 2
    Gold = 3
End Enum

データオブジェクトを作成してにバインドするときはDataGridView、次のようにします(注-配置はグローバルリスト(結果の)であり、ランナーはグローバルリスト(ランナーの)です:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Placements.Add(Result.None)
    Placements.Add(Result.Bronze)
    Placements.Add(Result.Silver)
    Placements.Add(Result.Gold)
    Runners.Add(New Runner("John", "Smith"))
    Runners.Add(New Runner("Jane", "Doe"))
    Runners.Add(New Runner("Bill", "Jones"))
    Column1.DataPropertyName = "FirstName"
    Column2.DataPropertyName = "LastName"
    Column3.DataPropertyName = "Placement"
    Column3.DataSource = Placements
    DataGridView1.DataSource = Runners
End Sub

これで、セルの値がComboBoxColumn変更されるたびに、列挙型を含むリストから新しい値を削除します。

Private Sub DataGridView1_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
    If (e.RowIndex > -1 And e.ColumnIndex = 2) Then
        Dim currentvalue As Result = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
        If currentvalue <> Result.None Then
            Placements.Remove(currentvalue)
        End If
    End If
End Sub

ドロップダウンの選択を変更するときは注意してください...このディスカッションDataGridViewのように、値が変更されるとすぐに値をコミットするように騙す必要がありComboBoxます。私はその議論からの答えを使用して、次のようなことをしました:

Private Sub DataGridView1_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) Handles DataGridView1.CurrentCellDirtyStateChanged
    Dim col As DataGridViewColumn = DataGridView1.Columns(DataGridView1.CurrentCell.ColumnIndex)
    If col.Name = "Column3" Then
        DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
        Dim selected As DataGridViewCell = DataGridView1.CurrentCell
        DataGridView1.CurrentCell = Nothing //This line and the next one simply hide
        DataGridView1.CurrentCell = selected //an odd display effect that occurs 
                                             //because we remove a value and change the
                                             //selection at the same time
    End If
End Sub

最後に、のDataErrorイベントを処理し、DataGridView空白のままにしてExceptions、列挙型のリストから値を削除するときにスローされないようにします。

これにより、そこまでの道のりの約90%が得られます。値を変更しても、リストにアイテムが再度追加されることはありません。たとえば、ゴールドからシルバーに変更した場合、ゴールドをリストに追加し直す必要があります。おそらく、古い値と新しい値を取得するために処理するイベントを把握し、列挙値に基づいて正しいインデックスで古い値をリストに挿入し直すことができます。

于 2013-02-14T00:40:06.757 に答える
1

DataGridViewのCellValidatingイベントを使用して、同じ値が複数回選択されているかどうかを確認することにしました。その場合、エラーメッセージが行ヘッダー列に表示されます。

エラーのあるコンボボックスは、エラーが解決されるまでフォーカスを失うことはありません。

Private Sub DataGridView1_CellValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating

    Dim headerText As String = DataGridView1.Columns(e.ColumnIndex).HeaderText

    'Abort validation if cell is not in the Mapping column. 
    If Not headerText.Equals("Column Mapping") Then Return

    'Clear error on current row.
    DataGridView1.Rows(e.RowIndex).ErrorText = Nothing
    e.Cancel = False

    Dim newMappingValue As XmlElement = DirectCast([Enum].Parse(GetType(XmlElement), e.FormattedValue), XmlElement)

    ' Abort validation if cell value equal XmlElement.None 
    If newMappingValue.Equals(XmlElement.None) Then Return

    For Each dgvRow As DataGridViewRow In DataGridView1.Rows
        Dim currentMappingValue As XmlElement = dgvRow.Cells.Item(headerText).Value

        If dgvRow.Index <> e.RowIndex Then
            If currentMappingValue.Equals(newMappingValue) Then
                DataGridView1.Rows(e.RowIndex).ErrorText = "Value already selected, please select a different value."
                e.Cancel = True
            End If
        End If
    Next

End Sub

ここに画像の説明を入力してください

于 2013-02-19T18:57:09.523 に答える