Vorgehensweise: Zugreifen auf Objekte in einer Windows Forms-DataGridViewComboBoxCell-Dropdownliste

Ebenso wie das ComboBox-Steuerelement ermöglichen auch die Typen DataGridViewComboBoxColumn und DataGridViewComboBoxCell das Hinzufügen beliebiger Objekte zu ihren Dropdownlisten. Mit diesem Feature können Sie komplexe Zustände in einer Dropdownliste darstellen, ohne die entsprechenden Objekte in einer separaten Sammlung speichern zu müssen.

Im Gegensatz zum ComboBox-Steuerelement besitzen die DataGridView-Typen keine SelectedItem-Eigenschaft zum Abrufen des aktuell ausgewählten Objekts. Stattdessen müssen Sie die Eigenschaft DataGridViewComboBoxColumn.ValueMember oder DataGridViewComboBoxCell.ValueMember auf den Namen einer Eigenschaft Ihres Geschäftsobjekts festlegen. Wenn der Benutzer eine Auswahl trifft, legt die angegebene Eigenschaft des Geschäftsobjekts die Eigenschaft der Zelle Value fest.

Um das Geschäftsobjekt über den Zellwert abzurufen, muss die Eigenschaft ValueMember eine Eigenschaft angeben, die einen Verweis auf das Geschäftsobjekt selbst zurückgibt. Wenn also der Typ des Geschäftsobjekts nicht Ihrer Kontrolle unterliegt, müssen Sie eine solche Eigenschaft hinzufügen, indem Sie den Typ durch Vererbung erweitern.

Die folgenden Verfahren zeigen, wie Sie eine Dropdownliste mit Geschäftsobjekten auffüllen und die Objekte über die Eigenschaft Value der Zelle abrufen.

So fügen Sie Geschäftsobjekte zur Dropdownliste hinzu

  1. Erstellen Sie eine neue DataGridViewComboBoxColumn, und füllen Sie ihre Items-Sammlung auf. Alternativ dazu können Sie auch die Eigenschaft DataSource der Spalte auf die Sammlung der Geschäftsobjekte festlegen. In diesem Fall können Sie jedoch nicht die Option „Unassigned“ (nicht zugewiesen) zur Dropdownliste hinzufügen, ohne ein entsprechendes Geschäftsobjekt in Ihrer Sammlung zu erstellen.

    DataGridViewComboBoxColumn assignedToColumn =
        new DataGridViewComboBoxColumn();
    
    // Populate the combo box drop-down list with Employee objects.
    foreach (Employee e in employees) assignedToColumn.Items.Add(e);
    
    // Add "unassigned" to the drop-down list and display it for
    // empty AssignedTo values or when the user presses CTRL+0.
    assignedToColumn.Items.Add("unassigned");
    assignedToColumn.DefaultCellStyle.NullValue = "unassigned";
    
    Dim assignedToColumn As New DataGridViewComboBoxColumn()
    
    ' Populate the combo box drop-down list with Employee objects. 
    For Each e As Employee In employees
        assignedToColumn.Items.Add(e)
    Next
    
    ' Add "unassigned" to the drop-down list and display it for 
    ' empty AssignedTo values or when the user presses CTRL+0. 
    assignedToColumn.Items.Add("unassigned")
    assignedToColumn.DefaultCellStyle.NullValue = "unassigned"
    
  2. Legen Sie die Eigenschaften DisplayMember und ValueMember fest. DisplayMember gibt die Eigenschaft des Geschäftsobjekts an, das in der Dropdownliste angezeigt werden soll. ValueMember gibt die Eigenschaft an, die einen Verweis auf das Geschäftsobjekt zurückgibt.

    assignedToColumn.DisplayMember = "Name";
    assignedToColumn.ValueMember = "Self";
    
    assignedToColumn.DisplayMember = "Name"
    assignedToColumn.ValueMember = "Self"
    
  3. Stellen Sie sicher, dass Ihr Geschäftsobjekttyp eine Eigenschaft enthält, die einen Verweis auf die aktuelle Instanz zurückgibt. Diese Eigenschaft muss mit dem Wert benannt werden, der im vorherigen Schritt ValueMember zugewiesen wurde.

    public Employee Self
    {
        get { return this; }
    }
    
    Public ReadOnly Property Self() As Employee
        Get
            Return Me
        End Get
    End Property
    

So rufen Sie das aktuell ausgewählte Geschäftsobjekt ab

  • Rufen Sie die Eigenschaft Value der Zelle ab, und wandeln Sie sie in den Geschäftsobjekttyp um.

    // Retrieve the Employee object from the "Assigned To" cell.
    Employee assignedTo = dataGridView1.Rows[e.RowIndex]
        .Cells["Assigned To"].Value as Employee;
    
    ' Retrieve the Employee object from the "Assigned To" cell.
    Dim assignedTo As Employee = TryCast(dataGridView1.Rows(e.RowIndex) _
        .Cells("Assigned To").Value, Employee)
    

Beispiel

Das vollständige Beispiel veranschaulicht die Verwendung von Geschäftsobjekten in einer Dropdownliste. Im Beispiel wird ein DataGridView-Steuerelement an eine Sammlung von Task-Objekten gebunden. Jedes Task-Objekt verfügt über eine AssignedTo-Eigenschaft. Diese gibt das Employee-Objekt an, das dieser Aufgabe derzeit zugewiesen ist. Die Spalte Assigned To zeigt den Eigenschaftswert Name für jeden zugewiesenen Mitarbeiter an, oder „Unassigned“ (nicht zugewiesen), wenn der Wert der Task.AssignedTo-Eigenschaft null lautet.

Führen Sie die folgenden Schritte aus, um sich das Verhalten dieses Beispiels anzusehen:

  1. Ändern Sie die Zuweisungen in der Spalte Assigned To, indem Sie verschiedene Werte aus den Dropdownlisten auswählen oder die Tastenkombination STRG+0 in einer Kombinationsfeldzelle drücken.

  2. Klicken Sie auf Generate Report, um die aktuellen Zuweisungen anzuzeigen. Dies zeigt, dass eine Änderung in der Spalte Assigned To automatisch zu einer Aktualisierung der Sammlung tasks führt.

  3. Klicken Sie auf eine Schaltfläche Request Status, um die RequestStatus-Methode des aktuellen Employee-Objekts für diese Zeile aufzurufen. Dies zeigt an, dass das ausgewählte Objekt erfolgreich abgerufen wurde.

using System;
using System.Text;
using System.Collections.Generic;
using System.Windows.Forms;

public class Form1 : Form
{
    private List<Employee> employees = new List<Employee>();
    private List<Task> tasks = new List<Task>();
    private Button reportButton = new Button();
    private DataGridView dataGridView1 = new DataGridView();

    [STAThread]
    public static void Main()
    {
        Application.Run(new Form1());
    }

    public Form1()
    {
        dataGridView1.Dock = DockStyle.Fill;
        dataGridView1.AutoSizeColumnsMode =
            DataGridViewAutoSizeColumnsMode.AllCells;
        reportButton.Text = "Generate Report";
        reportButton.Dock = DockStyle.Top;
        reportButton.Click += new EventHandler(reportButton_Click);

        Controls.Add(dataGridView1);
        Controls.Add(reportButton);
        Load += new EventHandler(Form1_Load);
        Text = "DataGridViewComboBoxColumn Demo";
    }

    // Initializes the data source and populates the DataGridView control.
    private void Form1_Load(object sender, EventArgs e)
    {
        PopulateLists();
        dataGridView1.AutoGenerateColumns = false;
        dataGridView1.DataSource = tasks;
        AddColumns();
    }

    // Populates the employees and tasks lists.
    private void PopulateLists()
    {
        employees.Add(new Employee("Harry"));
        employees.Add(new Employee("Sally"));
        employees.Add(new Employee("Roy"));
        employees.Add(new Employee("Pris"));
        tasks.Add(new Task(1, employees[1]));
        tasks.Add(new Task(2));
        tasks.Add(new Task(3, employees[2]));
        tasks.Add(new Task(4));
    }

    // Configures columns for the DataGridView control.
    private void AddColumns()
    {
        DataGridViewTextBoxColumn idColumn =
            new DataGridViewTextBoxColumn();
        idColumn.Name = "Task";
        idColumn.DataPropertyName = "Id";
        idColumn.ReadOnly = true;

        DataGridViewComboBoxColumn assignedToColumn =
            new DataGridViewComboBoxColumn();

        // Populate the combo box drop-down list with Employee objects.
        foreach (Employee e in employees) assignedToColumn.Items.Add(e);

        // Add "unassigned" to the drop-down list and display it for
        // empty AssignedTo values or when the user presses CTRL+0.
        assignedToColumn.Items.Add("unassigned");
        assignedToColumn.DefaultCellStyle.NullValue = "unassigned";

        assignedToColumn.Name = "Assigned To";
        assignedToColumn.DataPropertyName = "AssignedTo";
        assignedToColumn.AutoComplete = true;
        assignedToColumn.DisplayMember = "Name";
        assignedToColumn.ValueMember = "Self";

        // Add a button column.
        DataGridViewButtonColumn buttonColumn =
            new DataGridViewButtonColumn();
        buttonColumn.HeaderText = "";
        buttonColumn.Name = "Status Request";
        buttonColumn.Text = "Request Status";
        buttonColumn.UseColumnTextForButtonValue = true;

        dataGridView1.Columns.Add(idColumn);
        dataGridView1.Columns.Add(assignedToColumn);
        dataGridView1.Columns.Add(buttonColumn);

        // Add a CellClick handler to handle clicks in the button column.
        dataGridView1.CellClick +=
            new DataGridViewCellEventHandler(dataGridView1_CellClick);
    }

    // Reports on task assignments.
    private void reportButton_Click(object sender, EventArgs e)
    {
        StringBuilder report = new StringBuilder();
        foreach (Task t in tasks)
        {
            String assignment =
                t.AssignedTo == null ?
                "unassigned" : "assigned to " + t.AssignedTo.Name;
            report.AppendFormat("Task {0} is {1}.", t.Id, assignment);
            report.Append(Environment.NewLine);
        }
        MessageBox.Show(report.ToString(), "Task Assignments");
    }

    // Calls the Employee.RequestStatus method.
    void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
    {
        // Ignore clicks that are not on button cells.
        if (e.RowIndex < 0 || e.ColumnIndex !=
            dataGridView1.Columns["Status Request"].Index) return;

        // Retrieve the task ID.
        Int32 taskID = (Int32)dataGridView1[0, e.RowIndex].Value;

        // Retrieve the Employee object from the "Assigned To" cell.
        Employee assignedTo = dataGridView1.Rows[e.RowIndex]
            .Cells["Assigned To"].Value as Employee;

        // Request status through the Employee object if present.
        if (assignedTo != null)
        {
            assignedTo.RequestStatus(taskID);
        }
        else
        {
            MessageBox.Show(String.Format(
                "Task {0} is unassigned.", taskID), "Status Request");
        }
    }
}

public class Task
{
    public Task(Int32 id)
    {
        idValue = id;
    }

    public Task(Int32 id, Employee assignedTo)
    {
        idValue = id;
        assignedToValue = assignedTo;
    }

    private Int32 idValue;
    public Int32 Id
    {
        get { return idValue; }
        set { idValue = value; }
    }

    private Employee assignedToValue;
    public Employee AssignedTo
    {
        get { return assignedToValue; }
        set { assignedToValue = value; }
    }
}

public class Employee
{
    public Employee(String name)
    {
        nameValue = name;
    }

    private String nameValue;
    public String Name
    {
        get { return nameValue; }
        set { nameValue = value; }
    }

    public Employee Self
    {
        get { return this; }
    }

    public void RequestStatus(Int32 taskID)
    {
        MessageBox.Show(String.Format(
            "Status for task {0} has been requested from {1}.",
            taskID, nameValue), "Status Request");
    }
}
Imports System.Text
Imports System.Collections.Generic
Imports System.Windows.Forms

Public Class Form1
    Inherits Form

    Private employees As New List(Of Employee)
    Private tasks As New List(Of Task)
    Private WithEvents reportButton As New Button
    Private WithEvents dataGridView1 As New DataGridView

    <STAThread()> _
    Public Sub Main()
        Application.Run(New Form1)
    End Sub

    Sub New()
        dataGridView1.Dock = DockStyle.Fill
        dataGridView1.AutoSizeColumnsMode = _
            DataGridViewAutoSizeColumnsMode.AllCells
        reportButton.Text = "Generate Report"
        reportButton.Dock = DockStyle.Top

        Controls.Add(dataGridView1)
        Controls.Add(reportButton)
        Text = "DataGridViewComboBoxColumn Demo"
    End Sub

    ' Initializes the data source and populates the DataGridView control.
    Private Sub Form1_Load(ByVal sender As Object, _
        ByVal e As EventArgs) Handles Me.Load

        PopulateLists()
        dataGridView1.AutoGenerateColumns = False
        dataGridView1.DataSource = tasks
        AddColumns()

    End Sub

    ' Populates the employees and tasks lists. 
    Private Sub PopulateLists()
        employees.Add(New Employee("Harry"))
        employees.Add(New Employee("Sally"))
        employees.Add(New Employee("Roy"))
        employees.Add(New Employee("Pris"))
        tasks.Add(New Task(1, employees(1)))
        tasks.Add(New Task(2))
        tasks.Add(New Task(3, employees(2)))
        tasks.Add(New Task(4))
    End Sub

    ' Configures columns for the DataGridView control.
    Private Sub AddColumns()

        Dim idColumn As New DataGridViewTextBoxColumn()
        idColumn.Name = "Task"
        idColumn.DataPropertyName = "Id"
        idColumn.ReadOnly = True

        Dim assignedToColumn As New DataGridViewComboBoxColumn()

        ' Populate the combo box drop-down list with Employee objects. 
        For Each e As Employee In employees
            assignedToColumn.Items.Add(e)
        Next

        ' Add "unassigned" to the drop-down list and display it for 
        ' empty AssignedTo values or when the user presses CTRL+0. 
        assignedToColumn.Items.Add("unassigned")
        assignedToColumn.DefaultCellStyle.NullValue = "unassigned"

        assignedToColumn.Name = "Assigned To"
        assignedToColumn.DataPropertyName = "AssignedTo"
        assignedToColumn.AutoComplete = True
        assignedToColumn.DisplayMember = "Name"
        assignedToColumn.ValueMember = "Self"

        ' Add a button column. 
        Dim buttonColumn As New DataGridViewButtonColumn()
        buttonColumn.HeaderText = ""
        buttonColumn.Name = "Status Request"
        buttonColumn.Text = "Request Status"
        buttonColumn.UseColumnTextForButtonValue = True

        dataGridView1.Columns.Add(idColumn)
        dataGridView1.Columns.Add(assignedToColumn)
        dataGridView1.Columns.Add(buttonColumn)

    End Sub

    ' Reports on task assignments. 
    Private Sub reportButton_Click(ByVal sender As Object, _
        ByVal e As EventArgs) Handles reportButton.Click

        Dim report As New StringBuilder()
        For Each t As Task In tasks
            Dim assignment As String
            If t.AssignedTo Is Nothing Then
                assignment = "unassigned"
            Else
                assignment = "assigned to " + t.AssignedTo.Name
            End If
            report.AppendFormat("Task {0} is {1}.", t.Id, assignment)
            report.Append(Environment.NewLine)
        Next
        MessageBox.Show(report.ToString(), "Task Assignments")

    End Sub

    ' Calls the Employee.RequestStatus method.
    Private Sub dataGridView1_CellClick(ByVal sender As Object, _
        ByVal e As DataGridViewCellEventArgs) _
        Handles dataGridView1.CellClick

        ' Ignore clicks that are not on button cells. 
        If e.RowIndex < 0 OrElse Not e.ColumnIndex = _
            dataGridView1.Columns("Status Request").Index Then Return

        ' Retrieve the task ID.
        Dim taskID As Int32 = CInt(dataGridView1(0, e.RowIndex).Value)

        ' Retrieve the Employee object from the "Assigned To" cell.
        Dim assignedTo As Employee = TryCast(dataGridView1.Rows(e.RowIndex) _
            .Cells("Assigned To").Value, Employee)

        ' Request status through the Employee object if present. 
        If assignedTo IsNot Nothing Then
            assignedTo.RequestStatus(taskID)
        Else
            MessageBox.Show(String.Format( _
                "Task {0} is unassigned.", taskID), "Status Request")
        End If

    End Sub

End Class

Public Class Task

    Sub New(ByVal id As Int32)
        idValue = id
    End Sub

    Sub New(ByVal id As Int32, ByVal assignedTo As Employee)
        idValue = id
        assignedToValue = assignedTo
    End Sub

    Private idValue As Int32
    Public Property Id() As Int32
        Get
            Return idValue
        End Get
        Set(ByVal value As Int32)
            idValue = value
        End Set
    End Property

    Private assignedToValue As Employee
    Public Property AssignedTo() As Employee
        Get
            Return assignedToValue
        End Get
        Set(ByVal value As Employee)
            assignedToValue = value
        End Set
    End Property

End Class

Public Class Employee

    Sub New(ByVal name As String)
        nameValue = name
    End Sub

    Private nameValue As String
    Public Property Name() As String
        Get
            Return nameValue
        End Get
        Set(ByVal value As String)
            nameValue = value
        End Set
    End Property

    Public ReadOnly Property Self() As Employee
        Get
            Return Me
        End Get
    End Property

    Public Sub RequestStatus(ByVal taskID As Int32)
        MessageBox.Show(String.Format( _
            "Status for task {0} has been requested from {1}.", _
            taskID, nameValue), "Status Request")
    End Sub

End Class

Kompilieren des Codes

Für dieses Beispiel benötigen Sie Folgendes:

  • Verweise auf die Assemblys "System" und "System.Windows.Forms".

Weitere Informationen