Imports DevExpress.XtraGrid
Imports DevExpress.XtraGrid.Columns
Imports DevExpress.XtraGrid.Views.Grid

Public Class frmLookupGrid
    Public Property MultiSelect As Boolean
    Public Property AddNewValues As Boolean
    Public Property PreventDuplicates As Boolean
    Public Property DataSource As DataTable
    Public Property SelectedValues As List(Of String)

    Private dataColumn As Integer

    Private view As GridView
    Private grid As GridControl

    Private Sub frmLookupGrid_Load(sender As Object, e As EventArgs) Handles Me.Load
        view = viewLookup
        grid = gridLookup

        ' Datasource setzen
        grid.DataSource = DataSource

        ' Anzeige Eigeschaften setzen
        view.OptionsFind.AlwaysVisible = True
        view.OptionsSelection.MultiSelect = False

        If MultiSelect Then
            ' Selected Spalte anpassen
            Dim checkboxColumn = view.Columns.Item(0)
            checkboxColumn.Caption = " "
            checkboxColumn.MaxWidth = 10

            Text = "Wählen Sie einen oder mehrere Werte:"
            dataColumn = 1
        Else
            Text = "Wählen Sie einen Wert:"
            dataColumn = 0
        End If

        ' Alle Spalten linksbündig formatieren
        For columnIndex = dataColumn To DataSource.Columns.Count - 1
            Dim column As GridColumn = view.Columns.Item(columnIndex)
            column.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Near
        Next

        If AddNewValues Then
            view.OptionsBehavior.AllowAddRows = DevExpress.Utils.DefaultBoolean.True
            view.OptionsView.NewItemRowPosition = NewItemRowPosition.Top
        Else
            view.OptionsBehavior.AllowAddRows = DevExpress.Utils.DefaultBoolean.False
            view.OptionsView.NewItemRowPosition = NewItemRowPosition.None
        End If

        ' Wenn Selected Values nicht gesetzt ist, leere Liste anlegen
        If SelectedValues Is Nothing Then
            SelectedValues = New List(Of String)
        End If

        ' Bereits ausgewählte Werte im grid auswählen
        SyncItemsWithView(view)

        ' Focus auf Find panel setzen
        view.ShowFindPanel()
    End Sub

    Private Sub SyncItemsWithView(view As GridView)
        ' Wenn Vorbelegungen existieren, werden diese angehakt
        If SelectedValues.Count > 0 Then
            For i = 0 To view.DataRowCount - 1
                Dim rowHandle = view.GetRowHandle(i)
                Dim rowView As DataRowView = view.GetRow(rowHandle)

                If rowView IsNot Nothing Then
                    Dim row As DataRow = rowView.Row
                    Dim value = row.Item(dataColumn)

                    If SelectedValues.Contains(value) Then
                        If MultiSelect Then
                            row.Item(0) = True
                        Else
                            view.SelectRow(rowHandle)
                        End If
                    End If
                End If
            Next
        End If
    End Sub

    Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
        ' Filter vor dem Auslesen entfernen, damit alle Werte erfasst werden
        view.FindFilterText = String.Empty

        If MultiSelect Then
            Dim values As New List(Of String)

            For index = 0 To viewLookup.DataRowCount - 1
                Dim row As DataRow = view.GetDataRow(index)
                Dim selected As Boolean = row.Item(0)
                Dim value As String = row.Item(1)

                If selected Then
                    values.Add(value)
                End If
            Next

            ' Doppelte Werte entfernen, wenn konfiguriert
            If PreventDuplicates Then
                values = values.Distinct().ToList()
            End If

            SelectedValues = values
        Else
            Dim rowHandle As Integer = view.GetSelectedRows().ToList().First()
            Dim row As DataRow = view.GetDataRow(rowHandle)
            Dim value = row.Item(0)

            SelectedValues = New List(Of String) From {value}
        End If
    End Sub

    Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
        SelectedValues.Clear()
    End Sub

    Private Sub gridLookup_KeyUp(sender As Object, e As KeyEventArgs) Handles gridLookup.KeyUp
        If e.KeyCode = Keys.Escape Then
            Close()
        End If
    End Sub

    Private Sub viewLookup_CellValueChanging(sender As Object, e As Views.Base.CellValueChangedEventArgs) Handles viewLookup.CellValueChanging

        If e.RowHandle = GridControl.NewItemRowHandle Then
            Exit Sub
        End If

        Dim rowHandle = e.RowHandle
        Dim column = e.Column
    End Sub

    Private Sub viewLookup_ShowingEditor(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles viewLookup.ShowingEditor
        Dim rowHandleIsNewItemRow = (view.FocusedRowHandle = GridControl.NewItemRowHandle)
        Dim columnIsCheckboxColumn = view.FocusedColumn.FieldName = "SELECTED"

        ' Prevent editing of Data Column/allow editing for Checkbox Column and NewValue Row
        If rowHandleIsNewItemRow Or columnIsCheckboxColumn Then
            e.Cancel = False
        Else
            e.Cancel = True
        End If
    End Sub

    Private Sub viewLookup_RowClick(sender As Object, e As RowClickEventArgs) Handles viewLookup.RowClick
        ' If user double-clicks on a row
        If e.Clicks = 2 And e.Button = MouseButtons.Left Then
            ' And clicked row is a normal row
            If e.RowHandle >= 0 Then
                ' If multiselect is true, check the current row
                ' If multiselect is false, select the current row and close the window
                If MultiSelect = True Then
                    Dim row As DataRow = view.GetDataRow(e.RowHandle)
                    row.Item(0) = Not CBool(row.Item(0))
                Else
                    Dim row As DataRow = view.GetDataRow(e.RowHandle)
                    Dim value = row.Item(0)

                    SelectedValues = New List(Of String) From {value}

                    DialogResult = DialogResult.OK
                    Close()
                End If
            End If
        End If
    End Sub
End Class