Back to Devexpress

LookUpEdit Class

windowsforms-devexpress-dot-xtraeditors-e6132faf.md

latest53.5 KB
Original Source

LookUpEdit Class

A text box editor with a dropdown panel that displays data in a simple table layout.

Namespace : DevExpress.XtraEditors

Assembly : DevExpress.XtraEditors.v25.2.dll

NuGet Package : DevExpress.Win.Navigation

Declaration

csharp
[DefaultBindingProperty("EditValue")]
[DXLicenseWinFormsEditors]
public class LookUpEdit :
    LookUpEditBase
vb
<DefaultBindingProperty("EditValue")>
<DXLicenseWinFormsEditors>
Public Class LookUpEdit
    Inherits LookUpEditBase

The following members return LookUpEdit objects:

Remarks

Lookups are data-bound editors that display data source records in their dropdowns. Users can select one item (record) at a time. Users cannot edit records in the dropdown.

The following image shows the DevExpress WinForms Lookup.

Run Demo: LookUp Edit

The DevExpress WinForms Subscription includes four lookup controls:

Read the following topic to see the difference: Lookup Feature Matrix.

Bind to Data

A lookup is a data-bound control. Use the following properties to bind a lookup editor to a data source:

  • DataSource – Specifies the source of records.
  • DisplayMember – The data source field, whose values are visible to users. A value from this field is displayed in the lookup’s text box when a user selects a record.
  • ValueMember – The data source field with unique/key values. A value from this data field is assigned to the lookup’s EditValue property when a user selects a record.
  • KeyMember – Specifies the name of a key field (or multiple key fields). Use this property in Advanced Lookup Binding Mode.

Important

When a lookup editor is used to edit cell values in the Data Grid, the type of the ValueMember field must match the type of the field assigned to the grid’s lookup column (GridColumn.FieldName). Enable the lookup’s ThrowExceptionOnInvalidLookUpEditValueType option to detect data type issues.

Read the following topics for detailed information and examples:

How to Bind a Lookup to Data

The following example shows how to bind a lookup editor to data created at runtime:

csharp
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

public partial class Form1 : DevExpress.XtraEditors.XtraForm {
    public Form1() {
        InitializeComponent();
        // Binds the lookup to data.
        lookUpEdit1.Properties.DataSource = Employee.GetSampleData();
        // Sets the lookup's data fields.
        lookUpEdit1.Properties.DisplayMember = "FullName";
        lookUpEdit1.Properties.ValueMember = "ID";
        // Sets the lookup's value. Selects the first record.
        lookUpEdit1.EditValue = 0;
    }
}

public class Employee {
    public Employee(int iD, string firstName, string lastName) {
        ID = iD;
        FirstName = firstName;
        LastName = lastName;
    }
    public static List<Employee> GetSampleData() {
        return new List<Employee>() {
            new Employee(0, "Bart", "Arnaz"),
            new Employee(1, "Leah", "Simpson"),
            new Employee(2, "Arnold", "Schwartz"),
            new Employee(3, "William", "Zimmer"),
            new Employee(4, "Samantha", "Piper")
        };
    }
    // The 'ID' field must contain unique values.
    public int ID { get; private set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    [Display(Order = -1)]
    public string FullName {
        get {
            return string.Format("{0} {1}", FirstName, LastName);
        }
    }
}
vb
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel.DataAnnotations

Partial Public Class Form1
    Inherits DevExpress.XtraEditors.XtraForm

    Public Sub New()
        InitializeComponent()
        ' Binds the lookup to data.
        lookUpEdit1.Properties.DataSource = Employee.GetSampleData()
        ' Sets the lookup's data fields.
        lookUpEdit1.Properties.DisplayMember = "FullName"
        lookUpEdit1.Properties.ValueMember = "ID"
        ' Sets the lookup's value.
        lookUpEdit1.EditValue = 0
    End Sub
End Class

Public Class Employee
    Public Sub New(ByVal iD As Integer, ByVal firstName As String, ByVal lastName As String)
        Me.ID = iD
        Me.FirstName = firstName
        Me.LastName = lastName
    End Sub
    Public Shared Function GetSampleData() As List(Of Employee)
        Return New List(Of Employee)() From {
            New Employee(0, "Bart", "Arnaz"),
            New Employee(1, "Leah", "Simpson"),
            New Employee(2, "Arnold", "Schwartz"),
            New Employee(3, "William", "Zimmer"),
            New Employee(4, "Samantha", "Piper")
        }
    End Function
    ' The 'ID' field must contain unique values.
    Private privateID As Integer
    Public Property ID() As Integer
        Get
            Return privateID
        End Get
        Private Set(ByVal value As Integer)
            privateID = value
        End Set
    End Property
    Public Property FirstName() As String
    Public Property LastName() As String
    <Display(Order := -1)>
    Public ReadOnly Property FullName() As String
        Get
            Return String.Format("{0} {1}", FirstName, LastName)
        End Get
    End Property
End Class

The image below shows the result.

Tip

How to create a LookUp and use it in the Data Grid

Cascading Lookups

Lookups can filter their values based on the currently selected values of other lookups. See the following examples for detailed information:

Lookup Settings

The following table lists the most popular settings:

|

Property

|

Description

| | --- | --- | |

EditValue

|

Gets or sets the lookup’s value.

csharp
lookUpEdit1.EditValue = 0;
vb
lookUpEdit1.EditValue = 0

| |

TextEditStyle ProcessNewValue

|

Specifies whether users can type in the lookup’s text box.

Set the TextEditStyle property to Standard to allow users to type in the text box. Handle the ProcessNewValue event to parse entered values and add new records to the lookup’s data source.

csharp
// Enables adding new values.
lookUpEdit1.Properties.TextEditStyle = TextEditStyles.Standard;
lookUpEdit1.ProcessNewValue += new ProcessNewValueEventHandler(
    this.lookUpEdit1_ProcessNewValue
);

private void lookUpEdit1_ProcessNewValue(object sender, ProcessNewValueEventArgs e) {
    if((string)e.DisplayValue == String.Empty) return;
    List<Task> dataSource = (sender as LookUpEdit).Properties.DataSource as List<Task>;
    dataSource.Add(new Task(dataSource.Count) { Caption = (string)e.DisplayValue});
    e.Handled = true;
}
vb
' Enables adding new values.
lookUpEdit1.Properties.TextEditStyle = TextEditStyles.Standard
AddHandler lookUpEdit1.ProcessNewValue, AddressOf lookUpEdit1_ProcessNewValue

Private Sub lookUpEdit1_ProcessNewValue(ByVal sender As Object, ByVal e As ProcessNewValueEventArgs)
    If CStr(e.DisplayValue) = String.Empty Then
        Return
    End If
    Dim dataSource As List(Of Task) = TryCast((TryCast(sender, LookUpEdit)).Properties.DataSource, List(Of Task))
    dataSource.Add(New Task(dataSource.Count) With {.Caption = CStr(e.DisplayValue)})
    e.Handled = True
End Sub

| |

BestFitMode

|

Specifies the “best-fit” mode for lookup columns in the dropdown window. This feature proportionally resizes all columns to fit cell contents.

| |

NullText

|

Specifies a string that is displayed in the text box when the lookup’s value is null (for example, System.DBNull.Value).

| |

AllowNullInput

|

If enabled, users can press Delete, Backspace, or Ctrl+Delete to reset the lookup’s value to null. The TextEditStyle property should be set to DisableTextEditor or HideTextEditor.

| |

Columns

|

Use this property to access a collection of lookup columns.

| |

PopulateColumns()

|

Creates lookup columns for all fields in the data source.

| |

GetNotInListValue

|

Lookups can display columns that are not bound to data source fields. Handle the GetNotInListValue event to display unbound data in LookUpEdit.

| |

PopupWidth

|

Gets or sets the width of the dropdown window (in pixels). Use the PopupWidthMode property to specify whether the dropdown’s default width matches the width of the lookup or dropdown content.

| |

DropDownRows

|

Specifies the dropdown’s height (in rows). Use the DropDownItemHeight property to specify the height of a row (in pixels).

| |

CascadingOwner

|

Gets or sets the lookup editor whose value determines the filter criteria applied to the popup data source of the current lookup editor.

| |

CascadingMember

|

Gets or sets the name(s) of the foreign key field(s) by which the popup data source of the lookup editor is filtered. The field must be editable and accept new values (read-only fields are not supported).

| |

ImmediatePopup

|

Enable this option to display the dropdown immediately after a user has typed a character in the text box.

| |

SearchMode

|

Specifies the search mode (Auto-Complete, Auto-Filter, AutoSuggest, AutoSearch, etc.).

| |

AutoSearchColumnIndex

|

Specifies a column against which a lookup performs the incremental search in AutoComplete and OnlyInPopup modes.

| |

EditValueType

|

Gets or sets whether to enable the multiple item selection and specifies how the EditValue property stores selected items.

|

Set the SearchMode property to SearchMode.AutoSuggest or SearchMode.AutoSearch to enable item search. The lookup automatically sets the TextEditStyle property to Standard when you select either of these modes.

The difference between AutoSearch and AutoSuggest modes is as follows:

  • AutoSuggest runs a custom Task to return a collection of items and display them in the lookup’s dropdown. The lookup gets a virtual data source that updates every time a user inputs a new value. Use this mode in unbound lookups.
  • AutoSearch utilizes the built-in search algorithm to find items that meet the specified criteria in a data source.
  • AutoSearch mode is not supported by server-mode sources.
  • Both search modes are available for stand-alone lookups only.

Handle the PopupFilter event to specify a custom filter expression.

csharp
using DevExpress.Data.Filtering;
using DevExpress.XtraEditors.Controls;

private void LookUpEdit1_PopupFilter(object sender, PopupFilterEventArgs e)
{
    e.Criteria = CriteriaOperator.Parse(string.Format("DeliveryDate < '{0}'", DateTime.Today));
}
vb
Imports DevExpress.Data.Filtering
Imports DevExpress.XtraEditors.Controls

Private Sub LookUpEdit1_PopupFilter(ByVal sender As Object, ByVal e As PopupFilterEventArgs)
    e.Criteria = CriteriaOperator.Parse("ShipCountry == 'Brazil'")
End Sub

AutoSuggest Mode

When a user types text, the editor fires the AutoSuggest event (LookUpEdit.AutoSuggest / GridLookUpEdit.AutoSuggest) that runs a custom asynchronous task (a System.Threading.Tasks.Task object). This task performs a search against the given data set, and returns the ICollection object with records that match the entered text. This collection is automatically assigned to the editor’s DataSource and its entries appear in the editor drop-down menu.

Note

If an editor has an assigned data source, the editor switches to AutoSearch mode and fires the AutoSearch event.

This feature is in effect only for stand-alone editors.

AutoSuggest event parameters include:

  • QuerySuggestions — Assign a Task that performs the search and returns the suggestions collection.

  • Text — Returns the entered user text.

  • SetMinimumAnimationDuration — While a Task is searching for suggestions, the editor displays a loading indicator. To prevent this indicator from flickering when the search completes too quickly, the SetMinimumAnimationDuration method allows you to set the minimum on-screen duration.

  • SetHighlightRanges — Allows you to manually choose which parts of found items should be highlighted.

To test the AutoSuggest mode, run the AutoSuggest Lookup Demo Center module. You can click the “Open Solution” Ribbon button to view the complete demo code.

In this demo, suggestions (drop-down menu items) are retrieved on the QueryAsync task. The SetMinimumAnimationDuration method ensures the loading indicator is visible for at least one second.

csharp
lookUpEdit1.AutoSuggest += OnAutoSuggest;

void OnAutoSuggest(object sender, LookUpEditAutoSuggestEventArgs e) {
    // Set delay (if needed)
    e.SetMinimumAnimationDuration(TimeSpan.FromMilliseconds(1000));
    // Assign a Task that returns suggestions
    e.QuerySuggestions = WorldCities.QueryAsync(e.Text, e.CancellationToken);
}
vb
AddHandler lookUpEdit1.AutoSuggest, AddressOf OnAutoSuggest

Private Sub OnAutoSuggest(ByVal sender As Object, ByVal e As LookUpEditAutoSuggestEventArgs)
    ' Set delay (if needed)
    e.SetMinimumAnimationDuration(TimeSpan.FromMilliseconds(1000))
    ' Assign a Task that returns suggestions
    e.QuerySuggestions = WorldCities.QueryAsync(e.Text, e.CancellationToken)
End Sub

The code below demonstrates how this QueryAsync Task is implemented. The EnsureAllEntries method retrieves all locations from the source. If a user opens the editor drop-down menu, all entries are visible. Otherwise, the method compares user text with data source records.

csharp
public static Task<ICollection> QueryAsync(string text, CancellationToken cancellation) {
    var contains = IgnoreCaseComparisonFunctions.GetContains(
        CultureInfo.CurrentCulture.CompareInfo, CompareOptions.IgnoreCase);
    return Task.Run(() => {
        var entries = CsvDataHelper.EnsureAllEntries();
        var parts = text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
        if(parts.Length == 0)
            return entries as ICollection;
        else
            return entries.Where(e => {
                // Stop task if needed
                cancellation.ThrowIfCancellationRequested();
                return parts.All(x => e.Tags.Any(tag => contains(tag, x)));
            }).ToList() as ICollection;
    });
}
vb
Public Shared Function QueryAsync(ByVal text As String, ByVal cancellation As CancellationToken) As Task(Of ICollection)
    Dim contains = IgnoreCaseComparisonFunctions.GetContains(CultureInfo.CurrentCulture.CompareInfo, CompareOptions.IgnoreCase)
    Return Task.Run(Function()
                ' stop task if needed
        Dim entries = CsvDataHelper.EnsureAllEntries()
        Dim parts = text.Split(New Char() { " "c }, StringSplitOptions.RemoveEmptyEntries)
        If parts.Length = 0 Then
            Return TryCast(entries, ICollection)
        Else
            Return entries.Where(Function(e)
            cancellation.ThrowIfCancellationRequested()
            Return parts.All(Function(x) e.Tags.Any(Function(tag) contains(tag, x)))
            End Function).ToList()TryCast(, ICollection)
        End If
    End Function)
End Function

In this demo, the data source is the “Data\cities.csv” Excel file that stores approximately 13,000 city names. Each record also contains country and state names, country UN code, and Unicode city name. All records are extracted inside the custom Entry class.

csharp
public sealed class Entry {
    readonly static List<Entry> allEntries = new List<Entry>();
    public static IEnumerable<Entry> EnsureAllEntries() {
        lock(allEntries) {
            if(allEntries.Count == 0 && File.Exists("Data\cities.csv")) {
                var lines = File.ReadLines("Data\cities.csv").Skip(1);
                var entries = lines.Select(x => new Entry(x))
                        .OrderBy(e => e.Country)
                        .ThenBy(e => e.City);
                foreach(Entry entry in entries)
                    allEntries.Add(entry);
            }
            return allEntries;
        }
    }
//. . .
}
vb
Public NotInheritable Class Entry
    Private ReadOnly Shared allEntries As New List(Of Entry)()
    Public Shared Function EnsureAllEntries() As IEnumerable(Of Entry)
        SyncLock allEntries
            If allEntries.Count = 0 AndAlso File.Exists("Data\cities.csv") Then
                Dim lines = File.ReadLines("Data\cities.csv").Skip(1)
                Dim entries = lines.Select(Function(x) New Entry(x)).OrderBy(Function(e) e.Country).ThenBy(Function(e) e.City)
                For Each entryX As Entry In entries
                    allEntries.Add(entryX)
                Next entryX
            End If
            Return allEntries
        End SyncLock
    End Function
    //. . .
End Class

The Entry class contains data fields for Excel file columns, plus additional data fields for values combined from standard fields.

  • Tags - a portion of a record to be checked against an entered user text: City, Unicode City Name, and State Name;

  • Text - full location address in the “CountryName, CityName, StateName” format.

  • HtmlText - same as Text, but country name is displayed with grayed-out text. This field is used to custom draw lookup items (see the “Additional Customization” section below).

  • C#

  • VB.NET

csharp
public sealed class Entry {
    //standard fields
    public string Country { get; private set; }
    public string City { get; private set; }
    public string City_Unicode { get; private set; }
    public string Admin_Name_Unicode { get; private set; }
    public string Country_UN { get; private set; }
    //additional fields
    public string[] Tags { get; private set; }
    public string Text { get; private set; }
    public string HtmlText { get; private set; }
}
vb
Public NotInheritable Class Entry
    'standard fields
    Public Property Country() As String
    Public Property City() As String
    Public Property City_Unicode() As String
    Public Property Admin_Name_Unicode() As String
    Public Property Country_UN() As String
    'additional fields
    Public Property Tags() As String()
    Public Property Text() As String
    Public Property HtmlText() As String
End Class

You can call the LookUpEditBase.StartAutoSuggest method to manually trigger the AutoSuggest event.

Custom Item Draw

The HtmlText property declared in the Entry class is optional - it is not required to implement the auto-suggest functionality. This property is used to manually re-paint lookup items so that country names appear washed out. To do that, handle the RepositoryItemLookUpEdit.CustomDrawCell event.

csharp
lookUpEdit1.CustomDrawCell += OnCustomDrawCell;

void OnCustomDrawCell(object sender, LookUpCustomDrawCellArgs e) {
    e.DrawHtmlText(WorldCities.GetHtmlText(e.Row));
    e.Handled = true;
}
vb
Private lookUpEdit1.CustomDrawCell += AddressOf OnCustomDrawCell

Private Sub OnCustomDrawCell(ByVal sender As Object, ByVal e As LookUpCustomDrawCellArgs)
    e.DrawHtmlText(WorldCities.GetHtmlText(e.Row))
    e.Handled = True
End Sub

Custom Highlight Ranges

The QueryAsync Task compares user text with the entry Tags property. This property includes city name, city unicode name, and state name - country names are ignored. For example, the figure below illustrates that the demo database contains many Mexican cities.

If a user enters “ex”, from all Mexican cities only “M ex icali” and “M ex ico City” remain visible - the Task behaves correctly and filters out non-matching records. However, although the Task ignores countries, the editor highlights “ex” in country names as well.

This happens because there are two separate processes that take place in a lookup editor.

  1. A Task assigned to the QuerySuggestions property scans the data source and chooses records to show in a drop-down menu.
  2. A lookup editor scans items returned by the Task, and looks for user text matches.

If these two processes use different algorithms, a misleading highlight behavior similar to that mentioned above may happen. If this happens, define custom highlight range(s) with the SetHighlightRange / SetHighlightRanges methods. The demo code below uses the same logic as in the QueryAsync task to display the correct ranges.

csharp
void OnAutoSuggest(object sender, LookUpEditAutoSuggestEventArgs e) {
    //...
    // Set Custom Highlight Strategy
    e.SetHighlightRanges(HighlightTags(e.Text));
}

static Func<string, string, DisplayTextHighlightRange[]> HighlightTags(string pattern) {
    var indexOf = IgnoreCaseComparisonFunctions.GetIndexOf(
        CultureInfo.CurrentCulture.CompareInfo, CompareOptions.IgnoreCase);
    var parts = pattern.Split(new char[] { ' ' },
        StringSplitOptions.RemoveEmptyEntries);
    return (displayText, fieldName) => {
        var tags = displayText.Split(new string[] { ", " },
            StringSplitOptions.RemoveEmptyEntries);
        var ranges = new List<DisplayTextHighlightRange>();
        for(int i = 1/*skip country tag*/; i < tags.Length; i++) {
            int tagStart = displayText.IndexOf(tags[i]);
            for(int j = 0; j < parts.Length; j++) {
                int index = indexOf(tags[i], parts[j]);
                if(index != -1)
                    ranges.Add(new DisplayTextHighlightRange(tagStart + index, parts[j].Length));
            }
        }
        return ranges.ToArray();
    };
}
vb
Private Sub OnAutoSuggest(ByVal sender As Object, ByVal e As LookUpEditAutoSuggestEventArgs)
    '...
    ' Set Custom Highlight Strategy
    e.SetHighlightRanges(HighlightTags(e.Text))
End Sub

Shared Function HighlightTags(ByVal pattern As String) As Func(Of String, String, DisplayTextHighlightRange())
    Dim indexOf = IgnoreCaseComparisonFunctions.GetIndexOf(CultureInfo.CurrentCulture.CompareInfo, CompareOptions.IgnoreCase)
    Dim parts = pattern.Split(New Char() { " "c }, StringSplitOptions.RemoveEmptyEntries)
    Return Function(displayText, fieldName)
        Dim tags = displayText.Split(New String() { ", " }, StringSplitOptions.RemoveEmptyEntries)
        Dim ranges = New List(Of DisplayTextHighlightRange)()
        For i As Integer = 1 To tags.Length - 1 'skip country tag
            Dim tagStart As Integer = displayText.IndexOf(tags(i))
            For j As Integer = 0 To parts.Length - 1
                Dim index As Integer = indexOf(tags(i), parts(j))
                If index <> -1 Then
                    ranges.Add(New DisplayTextHighlightRange(tagStart + index, parts(j).Length))
                End If
            Next j
        Next i
        Return ranges.ToArray()
    End Function
End Function

The AutoSuggest event parameter offers a number of methods that you can use to define custom highlight ranges.

AutoSearch Mode

The AutoSearch mode allows users to search for required data source items.

Change Search Logic

Handle the AutoSearch event (LookUpEdit.AutoSearch \ GridLookUpEdit.AutoSearch) and use a SetParameters method overload to specify how the editor should compare user text with editor items.

  • parserKind parameter - specifies how user text parts divided by a space character should be combined (see the ColumnViewOptionsFind.ParserKind property for examples).
  • condition parameter - specifies which function should be used to build filter expressions (see the ColumnViewOptionsFind.Condition Data Grid property for examples).
  • field or fields[] parameter - allows you to limit the search by specific data fields only.
  • text parameter - allows you to replace the user text.

The following code snippet searches for items that start with user input.

csharp
lookUpEdit1.AutoSearch += OnAutoSearch;

void OnAutoSearch(object sender, LookUpEditAutoSearchEventArgs e) {
    string[] fields = new string[] { "ShipCity", "ShipCountry" };
    e.SetParameters(fields, e.Text, FindPanelParserKind.And, FilterCondition.StartsWith);
}
vb
Private lookUpEdit1.AutoSearch += AddressOf OnAutoSearch

Private Sub OnAutoSearch(ByVal sender As Object, ByVal e As LookUpEditAutoSearchEventArgs)
    Dim fields() As String = { "ShipCity", "ShipCountry" }
    e.SetParameters(fields, e.Text, FindPanelParserKind.And, FilterCondition.StartsWith)
End Sub

You can call the LookUpEditBase.StartAutoSearch method to manually trigger the AutoSearch event.

Custom Text Highlight Ranges

Lookup editors highlight text portions that match user text. Handle the AutoSearch event to implement custom highlight ranges. This mode uses same highlight API as the AutoSuggest mode does.

The following code snippet highlights the entire field value if it starts with the specified user text.

csharp
private void LookUpEdit1_AutoSearch(object sender, LookUpEditAutoSearchEventArgs e)
{
    e.SetParameters(FindPanelParserKind.And, FilterCondition.StartsWith);
    e.SetHighlightRanges(CustomHightlight(e.Text));
}

static Func<string, string, DisplayTextHighlightRange[]> CustomHightlight(string userText)
{
    return (displayText, fieldName) =>
    {
        if (fieldName == "ShipCity" || fieldName == "ShipCountry")
        {
            if (displayText.StartsWith(userText))
                return new DisplayTextHighlightRange[] {
                    new DisplayTextHighlightRange(0, displayText.Length) };
        }
        return null;
    };
}
vb
Private Sub LookUpEdit1_AutoSearch(ByVal sender As Object, ByVal e As LookUpEditAutoSearchEventArgs)
    e.SetParameters(FindPanelParserKind.And, FilterCondition.StartsWith)
    e.SetHighlightRanges(CustomHightlight(e.Text))
End Sub

Shared Function CustomHightlight(ByVal userText As String) As Func(Of String, String, DisplayTextHighlightRange())
    Return Function(displayText, fieldName)
        If fieldName = "ShipCity" OrElse fieldName = "ShipCountry" Then
            If displayText.StartsWith(userText) Then
                Return New DisplayTextHighlightRange() { New DisplayTextHighlightRange(0, displayText.Length) }
            End If
        End If
        Return Nothing
    End Function
End Function

Examples

How to Use a LookUpEdit as an In-Place Editor for Data Grid

The following example demonstrates how to create and customize an in-place LookUpEdit control (RepositoryItemLookUpEdit) to edit cell values in the CategoryID column.

The lookup editor displays category names in the edit box instead of category IDs (see the DisplayMember setting).

Play the animation to see the result:

View Example

csharp
using DevExpress.XtraEditors.Repository;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LookupEdit_StandardBinding {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            InitData();

            gridControl1.DataSource = Products;
            gridView1.Columns["UnitPrice"].DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric;
            gridView1.Columns["UnitPrice"].DisplayFormat.FormatString = "c2";

            // Create an in-place LookupEdit control.
            RepositoryItemLookUpEdit riLookup = new RepositoryItemLookUpEdit();
            riLookup.DataSource = Categories;
            riLookup.ValueMember = "ID";
            riLookup.DisplayMember = "CategoryName";

            // Enable the "best-fit" functionality mode in which columns have proportional widths and the popup window is resized to fit all the columns.
            riLookup.BestFitMode = DevExpress.XtraEditors.Controls.BestFitMode.BestFitResizePopup;
            // Specify the dropdown height.
            riLookup.DropDownRows = Categories.Count;

            // Enable the automatic completion feature. In this mode, when the dropdown is closed, 
            // the text in the edit box is automatically completed if it matches a DisplayMember field value of one of dropdown rows. 
            riLookup.SearchMode = DevExpress.XtraEditors.Controls.SearchMode.AutoComplete;
            // Specify the column against which an incremental search is performed in SearchMode.AutoComplete and SearchMode.OnlyInPopup modes
            riLookup.AutoSearchColumnIndex = 1;

            // Optionally hide the Description column in the dropdown.
            // riLookup.PopulateColumns();
            // riLookup.Columns["Description"].Visible = false;

            gridControl1.RepositoryItems.Add(riLookup);

            // Assign the in-place LookupEdit control to the grid's CategoryID column.
            // Note that the data types of the "ID" and "CategoryID" fields match.
            gridView1.Columns["CategoryID"].ColumnEdit = riLookup;
            gridView1.BestFitColumns();
        }

        List<Product> Products = new List<Product>();
        List<Category> Categories = new List<Category>();

        private void InitData() {
            Products.Add(new Product() { ProductName = "Sir Rodney's Scones", CategoryID = 3, UnitPrice = 10 });
            Products.Add(new Product() { ProductName = "Gustaf's Knäckebröd", CategoryID = 5, UnitPrice = 21 });
            Products.Add(new Product() { ProductName = "Tunnbröd", CategoryID = 5, UnitPrice = 9 });
            Products.Add(new Product() { ProductName = "Guaraná Fantástica", CategoryID = 1, UnitPrice = 4.5m });
            Products.Add(new Product() { ProductName = "NuNuCa Nuß-Nougat-Creme", CategoryID = 3, UnitPrice = 14 });
            Products.Add(new Product() { ProductName = "Gumbär Gummibärchen", CategoryID = 3, UnitPrice = 31.23m });
            Products.Add(new Product() { ProductName = "Rössle Sauerkraut", CategoryID = 7, UnitPrice = 45.6m });
            Products.Add(new Product() { ProductName = "Thüringer Rostbratwurst", CategoryID = 6, UnitPrice = 123.79m });
            Products.Add(new Product() { ProductName = "Nord-Ost Matjeshering", CategoryID = 8, UnitPrice = 25.89m });
            Products.Add(new Product() { ProductName = "Gorgonzola Telino", CategoryID = 4, UnitPrice = 12.5m });

            Categories.Add(new Category() { ID = 1, CategoryName = "Beverages", Description = "Soft drinks, coffees, teas, beers, and ales" });
            Categories.Add(new Category() { ID = 2, CategoryName = "Condiments", Description = "Sweet and savory sauces, relishes, spreads, and seasonings" });
            Categories.Add(new Category() { ID = 3, CategoryName = "Confections", Description = "Desserts, candies, and sweet breads" });
            Categories.Add(new Category() { ID = 4, CategoryName = "Dairy Products", Description = "Cheeses" });
            Categories.Add(new Category() { ID = 5, CategoryName = "Grains/Cereals", Description = "Breads, crackers, pasta, and cereal" });
            Categories.Add(new Category() { ID = 6, CategoryName = "Meat/Poultry", Description = "Prepared meats" });
            Categories.Add(new Category() { ID = 7, CategoryName = "Produce", Description = "Dried fruit and bean curd" });
            Categories.Add(new Category() { ID = 8, CategoryName = "Seafood", Description = "Seaweed and fish" });
        }
    }

    public class Product {
        public string ProductName { get; set; }
        public decimal UnitPrice { get; set; }
        public int CategoryID { get; set; }
    }

    public class Category {
        public int ID { get; set; }
        public string CategoryName { get; set; }
        public string Description { get; set; }
    }
}
vb
Imports DevExpress.XtraEditors.Repository
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Imports System.Windows.Forms

Namespace LookupEdit_StandardBinding
    Partial Public Class Form1
        Inherits Form

        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
            InitData()

            gridControl1.DataSource = Products
            gridView1.Columns("UnitPrice").DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric
            gridView1.Columns("UnitPrice").DisplayFormat.FormatString = "c2"

            ' Create an in-place LookupEdit control.
            Dim riLookup As New RepositoryItemLookUpEdit()
            riLookup.DataSource = Categories
            riLookup.ValueMember = "ID"
            riLookup.DisplayMember = "CategoryName"

            ' Enable the "best-fit" functionality mode in which columns have proportional widths and the popup window is resized to fit all the columns.
            riLookup.BestFitMode = DevExpress.XtraEditors.Controls.BestFitMode.BestFitResizePopup
            ' Specify the dropdown height.
            riLookup.DropDownRows = Categories.Count

            ' Enable the automatic completion feature. In this mode, when the dropdown is closed, 
            ' the text in the edit box is automatically completed if it matches a DisplayMember field value of one of dropdown rows. 
            riLookup.SearchMode = DevExpress.XtraEditors.Controls.SearchMode.AutoComplete
            ' Specify the column against which an incremental search is performed in SearchMode.AutoComplete and SearchMode.OnlyInPopup modes
            riLookup.AutoSearchColumnIndex = 1

            ' Optionally hide the Description column in the dropdown.
            ' riLookup.PopulateColumns();
            ' riLookup.Columns["Description"].Visible = false;

            gridControl1.RepositoryItems.Add(riLookup)

            ' Assign the in-place LookupEdit control to the grid's CategoryID column.
            ' Note that the data types of the "ID" and "CategoryID" fields match.
            gridView1.Columns("CategoryID").ColumnEdit = riLookup
            gridView1.BestFitColumns()
        End Sub

        Private Products As New List(Of Product)()
        Private Categories As New List(Of Category)()

        Private Sub InitData()
            Products.Add(New Product() With {.ProductName = "Sir Rodney's Scones", .CategoryID = 3, .UnitPrice = 10})
            Products.Add(New Product() With {.ProductName = "Gustaf's Knäckebröd", .CategoryID = 5, .UnitPrice = 21})
            Products.Add(New Product() With {.ProductName = "Tunnbröd", .CategoryID = 5, .UnitPrice = 9})
            Products.Add(New Product() With {.ProductName = "Guaraná Fantástica", .CategoryID = 1, .UnitPrice = 4.5D})
            Products.Add(New Product() With {.ProductName = "NuNuCa Nuß-Nougat-Creme", .CategoryID = 3, .UnitPrice = 14})
            Products.Add(New Product() With {.ProductName = "Gumbär Gummibärchen", .CategoryID = 3, .UnitPrice = 31.23D})
            Products.Add(New Product() With {.ProductName = "Rössle Sauerkraut", .CategoryID = 7, .UnitPrice = 45.6D})
            Products.Add(New Product() With {.ProductName = "Thüringer Rostbratwurst", .CategoryID = 6, .UnitPrice = 123.79D})
            Products.Add(New Product() With {.ProductName = "Nord-Ost Matjeshering", .CategoryID = 8, .UnitPrice = 25.89D})
            Products.Add(New Product() With {.ProductName = "Gorgonzola Telino", .CategoryID = 4, .UnitPrice = 12.5D})

            Categories.Add(New Category() With {.ID = 1, .CategoryName = "Beverages", .Description = "Soft drinks, coffees, teas, beers, and ales"})
            Categories.Add(New Category() With {.ID = 2, .CategoryName = "Condiments", .Description = "Sweet and savory sauces, relishes, spreads, and seasonings"})
            Categories.Add(New Category() With {.ID = 3, .CategoryName = "Confections", .Description = "Desserts, candies, and sweet breads"})
            Categories.Add(New Category() With {.ID = 4, .CategoryName = "Dairy Products", .Description = "Cheeses"})
            Categories.Add(New Category() With {.ID = 5, .CategoryName = "Grains/Cereals", .Description = "Breads, crackers, pasta, and cereal"})
            Categories.Add(New Category() With {.ID = 6, .CategoryName = "Meat/Poultry", .Description = "Prepared meats"})
            Categories.Add(New Category() With {.ID = 7, .CategoryName = "Produce", .Description = "Dried fruit and bean curd"})
            Categories.Add(New Category() With {.ID = 8, .CategoryName = "Seafood", .Description = "Seaweed and fish"})
        End Sub
    End Class

    Public Class Product
        Public Property ProductName() As String
        Public Property UnitPrice() As Decimal
        Public Property CategoryID() As Integer
    End Class

    Public Class Category
        Public Property ID() As Integer
        Public Property CategoryName() As String
        Public Property Description() As String
    End Class
End Namespace

How to Display SVG Icons in Dropdown

This example demonstrates how to display SVG icons from the SvgImageCollection within the LookUp editor’s dropdown.

csharp
using System;
using System.Collections.Generic;
using DevExpress.Utils;
using DevExpress.Utils.Svg;

public partial class Form1 : DevExpress.XtraEditors.XtraForm {
    public Form1() {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e) {
        lookUpEdit1.Properties.AllowNullInput = DefaultBoolean.True;
        lookUpEdit1.Properties.DataSource = InitData();
        lookUpEdit1.Properties.ValueMember = "ID";
        lookUpEdit1.Properties.DisplayMember = "DocumentFormat";

    }

    List<DataObject> InitData() {
        return new List<DataObject>() {
            new DataObject(0, "MS Word Binary File Format") { SvgImage = svgImageCollection1[0] },
            new DataObject(1, "Portable Document Format") { SvgImage = svgImageCollection1[1] },
            new DataObject(2, "Microsoft Excel Spreadsheet") { SvgImage = svgImageCollection1[2] },
            new DataObject(3, "Extensible Markup Language") { SvgImage = svgImageCollection1[3] }
        };
    }
}

public class DataObject {
    int fId;
    public DataObject(int fId, string format) {
        this.fId = fId;
        DocumentFormat = format;
    }
    public int ID {
        get { return fId; }
    }
    public SvgImage SvgImage { get; set; }
    public string DocumentFormat { get; set; }

}
vb
Imports System
Imports System.Collections.Generic
Imports DevExpress.Utils
Imports DevExpress.Utils.Svg

Partial Public Class Form1
    Inherits DevExpress.XtraEditors.XtraForm

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
        lookUpEdit1.Properties.AllowNullInput = DefaultBoolean.True
        lookUpEdit1.Properties.DataSource = InitData()
        lookUpEdit1.Properties.ValueMember = "ID"
        lookUpEdit1.Properties.DisplayMember = "DocumentFormat"

    End Sub

    Private Function InitData() As List(Of DataObject)
        Return New List(Of DataObject)() From {
            New DataObject(0, "MS Word Binary File Format") With {.SvgImage = svgImageCollection1(0)},
            New DataObject(1, "Portable Document Format") With {.SvgImage = svgImageCollection1(1)},
            New DataObject(2, "Microsoft Excel Spreadsheet") With {.SvgImage = svgImageCollection1(2)},
            New DataObject(3, "Extensible Markup Language") With {.SvgImage = svgImageCollection1(3)}
        }
    End Function
End Class

Public Class DataObject
    Private fId As Integer
    Public Sub New(ByVal fId As Integer, ByVal format As String)
        Me.fId = fId
        DocumentFormat = format
    End Sub
    Public ReadOnly Property ID() As Integer
        Get
            Return fId
        End Get
    End Property
    Public Property SvgImage() As SvgImage
    Public Property DocumentFormat() As String

End Class

How to Obtain a Value of a Cell Inside a Focused Row

When a LookUpEdit’s EditValue property changes, you may need to read the value of a cell located at the intersection of a selected row and a specific column. To do this, handle the LookUpEdit.EditValueChanged event and call the GetColumnValue(String) method.

csharp
private void lookUpEdit1_EditValueChanged(object sender, EventArgs e) {
    DevExpress.XtraEditors.LookUpEdit editor = sender as DevExpress.XtraEditors.LookUpEdit;
    object value = editor.GetColumnValue("aFieldName");
}
vb
Private Sub lookUpEdit1_EditValueChanged(ByVal sender As Object, ByVal e As EventArgs)
    Dim editor As DevExpress.XtraEditors.LookUpEdit = TryCast(sender, DevExpress.XtraEditors.LookUpEdit)
    Dim value As Object = editor.GetColumnValue("aFieldName")
End Sub

You may also call the GetDataSourceRowByKeyValue(Object) method instead of GetColumnValue. This method retrieves row objects of a data source assigned to the editor’s Properties.DataSource property. For example, if your editor is bound to a DataTable object, use the code below.

csharp
private void lookUpEdit1_EditValueChanged(object sender, System.EventArgs e) {
    DevExpress.XtraEditors.LookUpEdit editor = sender as DevExpress.XtraEditors.LookUpEdit;
    DataRowView row = editor.Properties.GetDataSourceRowByKeyValue(editor.EditValue) as DataRowView;
    object value = row["aFieldName"];
}
vb
Private Sub lookUpEdit1_EditValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim editor As DevExpress.XtraEditors.LookUpEdit = CType(sender, DevExpress.XtraEditors.LookUpEdit)
    Dim row As DataRowView = CType(editor.Properties.GetDataSourceRowByKeyValue(editor.EditValue), DataRowView)
    Dim value As Object = row("aFieldName")
End Sub

How to Process New Values (ProcessNewValue Event)

This example handles the ProcessNewValue event to parse entered values and add new records to the lookup’s data source. Refer to the following KB article for additional information: How to Use the ProcessNewValue Event of a LookUp Editor.

View Example

Knowledge Base Articles:

Implements

IXtraResizableControl

Inheritance

Show 15 items

Object MarshalByRefObject Component Control DevExpress.XtraEditors.XtraControl ControlBase BaseControl BaseEdit TextEdit ButtonEdit PopupBaseEdit PopupBaseAutoSearchEdit LookUpEditBase LookUpEdit TimeZoneEdit

See Also

LookUpEdit Members

Lookup Editors

Lookup Main Settings

Cascading Lookups

ComboBox Mode - Enter New Values

DevExpress.XtraEditors Namespace