windowsforms-devexpress-dot-xtraeditors-8a7459cd.md
An editor that has lookup functionality using a feature-rich dropdown Data Grid (GridControl). You can display lookup records in a tabular format, banded tabular format, or as tiles (which can be arranged in one or multiple columns/rows, rendered as a list or a Kanban board).
Namespace : DevExpress.XtraEditors
Assembly : DevExpress.XtraGrid.v25.2.dll
NuGet Packages : DevExpress.Win.Grid, DevExpress.Win.Navigation
[DXLicenseWinForms]
public class GridLookUpEdit :
GridLookUpEditBase
<DXLicenseWinForms>
Public Class GridLookUpEdit
Inherits GridLookUpEditBase
The following members return GridLookUpEdit objects:
A lookup editor is an editor with an embedded dropdown window that displays lookup records (the records from which an end user can select). When a lookup record is selected, the editor’s value (the BaseEdit.EditValue bindable property) and display text are modified accordingly.
GridLookUpEdit can display lookup records in the dropdown using multiple data presentation formats (Views), which you can choose with the PopupViewType property.
Use the PopupView property to customize the dropdown view. At design time, you can use the integrated Data Grid Designer to customize the dropdown/popup view.
Displays data in a tabular form. The following features, and many more, can be employed for the Grid View embedded in GridLookUpEdit: data sorting, grouping, filtering, summaries, hiding column headers, changing row height, etc.
Read the following topic for detailed information: Grid View.
Displays records as tiles, using one of the following layout modes: default (standard table layout), list (tiles have no space between them), and Kanban. This View includes the Tile Template feature, which helps you arrange fields relative to other fields, specify absolute or relative field display bounds, etc. In-place editors are supported when you use HTML-based templates.
Read the following topic for detailed information: Tile View.
Displays data in a tabular form and allows you to group columns into bands.
Read the following topic for detailed information: Banded Grid Views.
Displays data in a tabular form, allows you to group columns into bands, and supports complex data cell arrangements.
Read the following topic for detailed information: Banded Grid Views.
When you change the data presentation format (RepositoryItemGridLookUpEditBase.PopupViewType), the GridLookUpEdit control creates a corresponding View object (accessible from the RepositoryItemGridLookUpEditBase.PopupView property). You may need to perform additional customizations of the created View. For instance, after you activate the BandedView or AdvBandedView format, you need to manually create bands and add columns to the bands. Otherwise, these Views cannot display data.
At design time, you can customize the View with the Data Grid Designer. To open the designer, do one of the following:
Note
You can use the Grid Control and View’s methods only when the drop-down window is open if you want to access the data source and calculated data. To access the View, handle the QueryPopUp or Popup event.
private void gridLookUpEdit1_Properties_QueryPopUp(object sender, CancelEventArgs e) {
// Cast to SearchLookUpEdit or GridLookUpEdit depending on which control you use
GridLookUpEdit gridLookUpEdit = sender as GridLookUpEdit;
gridLookUpEdit.Properties.PopupView.Columns["ID"].Visible = false;
}
Private Sub gridLookUpEdit1_Properties_QueryPopUp(ByVal sender As Object, ByVal e As CancelEventArgs)
' Cast to SearchLookUpEdit or GridLookUpEdit depending on which control you use
Dim gridLookUpEdit As GridLookUpEdit = TryCast(sender, GridLookUpEdit)
gridLookUpEdit.Properties.PopupView.Columns("ID").Visible = False
End Sub
When the drop-down window is closed, use the data source’s methods.
If you customize the View in an event, do not use objects to identify the View, columns, and so on – use field names, captions, etc., instead. The example below shows how to identify a column in a CustomDrawCell event handler.
private void SearchLookUpEdit1View_CustomDrawCell(object sender, >DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e) {
if (e.Column.FieldName == "MyFieldName") {
//...
}
}
Private Sub SearchLookUpEdit1View_CustomDrawCell(ByVal sender As Object, ByVal >e As DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs) _
Handles searchLookUpEdit1View.CustomDrawCell
If e.Column.FieldName = "MyFieldName" Then
'...
End If
End Sub
To learn how to set up lookup editors in different binding modes, see the following topics:
You may want to filter the popup data source of one (secondary) lookup editor based on the value of another (primary) lookup editor. This scenario is covered in the following topic:
In case you need to access lookup grid columns before the editor has created them, call the RepositoryItemGridLookUpEditBase.PopulateViewColumns method to manually trigger column generation.
RepositoryItemGridLookUpEditBase.PopupViewTypeGets or sets the type of View used to visualize data in the dropdown.RepositoryItemGridLookUpEditBase.PopupView
Gets or sets the View used to visualize data in the dropdown.
The View property has settings to change the grid appearance, access columns, create unbound columns, apply data grouping, filtering, summaries, etc.
For instance, if you use a ColumnView descendant (for example, GridView), you can use the ColumnView.Columns property to customize the column collection. To set up columns at design time, use the GridControl’s designer, which can be invoked from the RepositoryItemGridLookUpEditBase.PopupView property in the Properties window.
RepositoryItemLookUpEditBase.TextEditStyle propertyEnables the text editing feature in the edit box.RepositoryItemGridLookUpEdit.SearchModeGets or sets whether the editor automatically completes the value, filters the drop-down list, or provides custom suggestions when the user types a query in the edit box.RepositoryItemLookUpEditBase.ProcessNewValue eventEnables you to add a new record to the lookup data source (RepositoryItemLookUpEditBase.DataSource) for new values entered in the edit box.RepositoryItemLookUpEditBase.BestFitModeGets or sets the “best-fit” mode for columns in the dropdown window.RepositoryItem.NullTextGets or sets the text that presents the editor’s null value ( null , System.DBNull.Value and RepositoryItemDateEdit.NullDate - for DateEdit).RepositoryItemPopupBaseAutoSearchEdit.ImmediatePopupGets or sets whether the popup window is displayed immediately after an end user has typed a character in the edit box.
To embed a GridLookUpEdit in a cell within a container control (XtraGrid, XtraTreeList, etc.), use the RepositoryItemGridLookUpEdit component. See the “Repository Items” section in the Editors and Simple Controls topic for more information.
Note
The GridLookUpEdit control does not support Instant Feedback Mode.
Note
You can use the Grid Control and View’s methods only when the drop-down window is open if you want to access the data source and calculated data. To access the View, handle the QueryPopUp or Popup event.
private void gridLookUpEdit1_Properties_QueryPopUp(object sender, CancelEventArgs e) {
// Cast to SearchLookUpEdit or GridLookUpEdit depending on which control you use
GridLookUpEdit gridLookUpEdit = sender as GridLookUpEdit;
gridLookUpEdit.Properties.PopupView.Columns["ID"].Visible = false;
}
Private Sub gridLookUpEdit1_Properties_QueryPopUp(ByVal sender As Object, ByVal e As CancelEventArgs)
' Cast to SearchLookUpEdit or GridLookUpEdit depending on which control you use
Dim gridLookUpEdit As GridLookUpEdit = TryCast(sender, GridLookUpEdit)
gridLookUpEdit.Properties.PopupView.Columns("ID").Visible = False
End Sub
When the drop-down window is closed, use the data source’s methods.
If you customize the View in an event, do not use objects to identify the View, columns, and so on – use field names, captions, etc., instead. The example below shows how to identify a column in a CustomDrawCell event handler.
private void SearchLookUpEdit1View_CustomDrawCell(object sender, >DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e) {
if (e.Column.FieldName == "MyFieldName") {
//...
}
}
Private Sub SearchLookUpEdit1View_CustomDrawCell(ByVal sender As Object, ByVal >e As DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs) _
Handles searchLookUpEdit1View.CustomDrawCell
If e.Column.FieldName = "MyFieldName" Then
'...
End If
End Sub
Note
The Find Panel is not supported for the GridLookUpEdit ‘s dropdown GridControl. If you need to enable the Find Panel for a look-up editor, use the SearchLookUpEdit control instead.
If you want users to be able to search for lookup items, change the RepositoryItemGridLookUpEdit.SearchMode property to either AutoSuggest or AutoSearch. The RepositoryItemGridLookUpEdit.TextEditStyle property automatically switches to Standard when you select either of these modes.
Difference between AutoSearch and AutoSuggest modes:
AutoSuggest runs a custom Task to return a collection of items for the drop-down panel. As a result, the editor has a virtual data source that changes every time a user text changes. This mode is primarily used with unbound editors.
AutoSearch uses the default search logic to find required items in the data source to which this lookup is bound.
AutoSearch mode is not currently available with server-mode editor sources.
Both modes are available for stand-alone editors only.
Tip
GridControl, GridLookUpEdit, and SearchLookUpEdit support AI-powered Semantic Search. Unlike standard keyword-based search, semantic search leverages Natural Language Processing (NLP) to analyze search queries beyond exact keyword matching. See the following help topic for additional information: Semantic Search.
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.
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);
}
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.
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;
});
}
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.
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;
}
}
//. . .
}
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).
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; }
}
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.
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.
lookUpEdit1.CustomDrawCell += OnCustomDrawCell;
void OnCustomDrawCell(object sender, LookUpCustomDrawCellArgs e) {
e.DrawHtmlText(WorldCities.GetHtmlText(e.Row));
e.Handled = true;
}
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
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.
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.
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();
};
}
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.
The AutoSearch mode allows users to search for required data source items.
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.
The following code snippet searches for items that start with user input.
lookUpEdit1.AutoSearch += OnAutoSearch;
void OnAutoSearch(object sender, LookUpEditAutoSearchEventArgs e) {
string[] fields = new string[] { "ShipCity", "ShipCountry" };
e.SetParameters(fields, e.Text, FindPanelParserKind.And, FilterCondition.StartsWith);
}
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.
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.
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;
};
}
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
The following example demonstrates how to create and customize a GridLookUpEdit control at runtime.
In the example, a lookup editor is used to edit the values of the “ProductID” field in the “Order Details” table (the Northwind database). It must display a list of available products in the dropdown, which are stored in the “Products” table in the database. By selecting a row from the dropdown, an end user can change the current order’s product. Also, a data navigator will be created that will assist an end user to navigate through the “Order Details” table.
To implement the required functionality, the following key properties of the lookup editor must be set:
The result of the example is shown in the following image:
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Columns;
using System.Data.OleDb;
// A lookup editor created at runtime.
GridLookUpEdit gridLookup;
// A navigator control to navigate the "Order Details" table.
DataNavigator dataNav;
// DataView for the "Order Details" table.
DataView dvMain;
// DataView for the "Products" table.
DataView dvDropDown;
//...
private void Form1_Load(object sender, System.EventArgs e) {
gridLookup = new GridLookUpEdit();
gridLookup.Bounds = new Rectangle(10, 40, 200, 20);
this.Controls.Add(gridLookup);
dataNav = new DataNavigator();
dataNav.Bounds = new Rectangle(10, 10, 250, 20);
this.Controls.Add(dataNav);
InitData();
InitLookUp();
dataNav.DataSource = dvMain;
}
private void InitData() {
// Dataset to provide data from the database
DataSet ds = new DataSet();
string connestionString =
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\DB\\nwind.mdb";
// Connect to the "Order Details" table
System.Data.OleDb.OleDbDataAdapter dbAdapter =
new OleDbDataAdapter("SELECT * FROM [Order Details]", connestionString);
// Load data from the "Order Details" table to the dataset
dbAdapter.Fill(ds, "Order Details");
// Connect to the "Products" table
dbAdapter = new OleDbDataAdapter("SELECT * FROM Products", connestionString);
// Load data from the "Products" table into the dataset
dbAdapter.Fill(ds, "Products");
DataViewManager dvm = new DataViewManager(ds);
dvMain = dvm.CreateDataView(ds.Tables["Order Details"]);
dvDropDown = dvm.CreateDataView(ds.Tables["Products"]);
}
private void InitLookUp() {
// Bind the edit value to the ProductID field of the "Order Details" table;
// the edit value matches the value of the ValueMember field.
gridLookup.DataBindings.Add("EditValue", dvMain, "ProductID");
// Prevent columns from being automatically created when a data source is assigned.
gridLookup.Properties.PopupView.OptionsBehavior.AutoPopulateColumns = false;
// The data source for the dropdown rows
gridLookup.Properties.DataSource = dvDropDown;
// The field for the editor's display text.
gridLookup.Properties.DisplayMember = "ProductName";
// The field matching the edit value.
gridLookup.Properties.ValueMember = "ProductID";
// Add two columns in the dropdown:
// A column to display the values of the ProductID field;
GridColumn col1 = gridLookup.Properties.PopupView.Columns.AddField("ProductID");
col1.VisibleIndex = 0;
col1.Caption = "Product ID";
// A column to display the values of the ProductName field.
GridColumn col2 = gridLookup.Properties.PopupView.Columns.AddField("ProductName");
col2.VisibleIndex = 1;
col2.Caption = "Product Name";
// Set column widths according to their contents.
gridLookup.Properties.PopupView.BestFitColumns();
// Specify the total dropdown width.
gridLookup.Properties.PopupFormWidth = 300;
}
Imports DevExpress.XtraEditors
Imports DevExpress.XtraGrid.Columns
Imports System.Data.OleDb
' A lookup editor created at runtime.
Dim gridLookup As GridLookUpEdit
' A navigator control to navigate the "Order Details" table.
Dim dataNav As DataNavigator
' DataView for the "Order Details" table.
Dim dvMain As DataView
' DataView for the "Products" table.
Dim dvDropDown As DataView
'...
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.Load
gridLookup = New GridLookUpEdit()
gridLookup.Bounds = New Rectangle(10, 40, 200, 20)
Me.Controls.Add(gridLookup)
dataNav = New DataNavigator()
dataNav.Bounds = New Rectangle(10, 10, 250, 20)
Me.Controls.Add(dataNav)
InitData()
InitLookUp()
dataNav.DataSource = dvMain
End Sub
Private Sub InitData()
' Dataset to provide data from the database
Dim ds As New DataSet()
Dim connestionString As String = _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\DB\nwind.mdb"
' Connect to the "Order Details" table
Dim dbAdapter As New OleDbDataAdapter("SELECT * FROM [Order Details]", connestionString)
' Load data from the "Order Details" table to the dataset
dbAdapter.Fill(ds, "Order Details")
' Connect to the "Products" table
dbAdapter = New OleDbDataAdapter("SELECT * FROM Products", connestionString)
' Load data from the "Products" table into the dataset
dbAdapter.Fill(ds, "Products")
Dim dvm As New DataViewManager(ds)
dvMain = dvm.CreateDataView(ds.Tables("Order Details"))
dvDropDown = dvm.CreateDataView(ds.Tables("Products"))
End Sub
Private Sub InitLookUp()
' Bind the edit value to the ProductID field of the "Order Details" table;
' the edit value matches the value of the ValueMember field.
gridLookup.DataBindings.Add("EditValue", dvMain, "ProductID")
' Prevent columns from being automatically created when a data source is assigned.
gridLookup.Properties.PopupView.OptionsBehavior.AutoPopulateColumns = False
' The data source for the dropdown rows
gridLookup.Properties.DataSource = dvDropDown
' The field for the editor's display text.
gridLookup.Properties.DisplayMember = "ProductName"
' The field matching the edit value.
gridLookup.Properties.ValueMember = "ProductID"
' Add two columns in the dropdown:
' A column to display the values of the ProductID field;
Dim col1 As GridColumn = gridLookup.Properties.PopupView.Columns.AddField("ProductID")
col1.VisibleIndex = 0
col1.Caption = "Product ID"
' A column to display the values of the ProductName field.
Dim col2 As GridColumn = gridLookup.Properties.PopupView.Columns.AddField("ProductName")
col2.VisibleIndex = 1
col2.Caption = "Product Name"
' Set column widths according to their contents.
gridLookup.Properties.PopupView.BestFitColumns()
' Specify the total dropdown width.
gridLookup.Properties.PopupFormWidth = 300
End Sub
Assume that a GridLookUpEdit control needs to be used in multiple places, and all editors must display data from one predefined data source and contain predefined columns. In this instance, you can create a custom GridLookUpEdit control.
This example shows how to create a custom GridLookUpEdit control, and initialize its properties as required. The structure of descendant classes is based on the code template shown in the Custom Editors.Editors Structure topic.
To customize the control’s settings, the OnLoaded method is overridden. In this method, the control’s DataSource, columns and some other options are initialized. Note that columns created in this method are not accessible at design time.
using System.Drawing;
using System.Reflection;
using System.ComponentModel;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraEditors.Registrator;
using DevExpress.XtraEditors.Drawing;
using DevExpress.XtraEditors.ViewInfo;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Grid;
using System.Data;
namespace DevExpress.MyGridLookUpEditors {
//The attribute that points to the registration method
[UserRepositoryItem("RegisterMyGridLookUpEdit")]
public class RepositoryItemMyGridLookUpEdit : RepositoryItemGridLookUpEdit {
//The static constructor which calls the registration method
static RepositoryItemMyGridLookUpEdit() { RegisterMyGridLookUpEdit(); }
//Initialize new properties
public RepositoryItemMyGridLookUpEdit() {
}
protected override void OnLoaded() {
base.OnLoaded();
if (IsDesignMode) return;
// Create two columns
GridColumn colId = new GridColumn();
colId.FieldName = colId.Caption = "ID";
colId.VisibleIndex = 0;
GridColumn colName = new GridColumn();
colName.FieldName = colName.Caption = "Name";
colName.VisibleIndex = 1;
GridView gView = this.View;
gView.Columns.Clear();
gView.Columns.Add(colId);
gView.Columns.Add(colName);
// Hide the group panel
gView.OptionsView.ShowGroupPanel = true;
// Initialize data source
DisplayMember = "Name";
ValueMember = "ID";
DataSource = GetData();
}
private DataTable GetData() {
DataTable table = new DataTable();
table.Columns.Add(new DataColumn("ID", typeof(int)));
table.Columns.Add(new DataColumn("Name", typeof(string)));
table.Rows.Add(new object[] { 0, "A" });
table.Rows.Add(new object[] { 1, "B" });
table.Rows.Add(new object[] { 2, "C" });
return table;
}
//The unique name for the custom editor
public const string MyGridLookUpEditName = "MyGridLookUpEdit";
//Return the unique name
public override string EditorTypeName { get { return MyGridLookUpEditName; } }
//Register the editor
public static void RegisterMyGridLookUpEdit() {
//Icon representing the editor within a container editor's Designer
Image img = null;
EditorRegistrationInfo.Default.Editors.Add(new EditorClassInfo(MyGridLookUpEditName,
typeof(MyGridLookUpEdit), typeof(RepositoryItemMyGridLookUpEdit),
typeof(GridLookUpEditBaseViewInfo), new ButtonEditPainter(), true, img));
}
//Override the Assign method
public override void Assign(RepositoryItem item) {
BeginUpdate();
try {
base.Assign(item);
RepositoryItemMyGridLookUpEdit source =
item as RepositoryItemMyGridLookUpEdit;
if (source == null) return;
}
finally {
EndUpdate();
}
}
}
public class MyGridLookUpEdit : GridLookUpEdit {
//The static constructor which calls the registration method
static MyGridLookUpEdit() {
RepositoryItemMyGridLookUpEdit.RegisterMyGridLookUpEdit(); }
//Initialize the new instance
public MyGridLookUpEdit() {
//...
}
//Return the unique name
public override string EditorTypeName { get { return
RepositoryItemMyGridLookUpEdit.MyGridLookUpEditName; } }
//Override the Properties property
//Simply type-cast the object to the custom repository item type
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public new RepositoryItemMyGridLookUpEdit Properties {
get { return base.Properties as RepositoryItemMyGridLookUpEdit; }
}
}
}
Imports System.Reflection
Imports System.Drawing
Imports System.ComponentModel
Imports System.Windows.Forms
Imports DevExpress.XtraEditors
Imports DevExpress.XtraEditors.Repository
Imports DevExpress.XtraEditors.Registrator
Imports DevExpress.XtraEditors.Drawing
Imports DevExpress.XtraEditors.ViewInfo
Imports DevExpress.XtraGrid.Columns
Imports DevExpress.XtraGrid.Views.Grid
'The attribute that points to the registration method
<UserRepositoryItem("RegisterMyGridLookUpEdit")> _
Public Class RepositoryItemMyGridLookUpEdit
Inherits RepositoryItemGridLookUpEdit
'The static constructor which calls the registration method
Shared Sub New()
RegisterMyGridLookUpEdit()
End Sub
'Initialize new properties
Public Sub New()
End Sub
Protected Overrides Sub OnLoaded()
MyBase.OnLoaded()
If IsDesignMode Then Return
' Create two columns
Dim colId As New GridColumn
colId.FieldName = "ID"
colId.Caption = "ID"
colId.VisibleIndex = 0
Dim colName As New GridColumn
colName.FieldName = "Name"
colName.Caption = "Name"
colName.VisibleIndex = 1
Dim gView As GridView = View
gView.Columns.Clear()
gView.Columns.Add(colId)
gView.Columns.Add(colName)
' Hide the group panel
gView.OptionsView.ShowGroupPanel = True
' Initialize data source
DisplayMember = "Name"
ValueMember = "ID"
DataSource = GetData()
End Sub
Public Function GetData() As DataTable
Dim table As New DataTable()
table.Columns.Add(New DataColumn("ID", GetType(Integer)))
table.Columns.Add(New DataColumn("Name", GetType(String)))
table.Rows.Add(New Object() {0, "A"})
table.Rows.Add(New Object() {1, "B"})
table.Rows.Add(New Object() {2, "C"})
Return table
End Function
'The unique name for the custom editor
Public Const MyGridLookUpEditName As String = "MyGridLookUpEdit"
'Return the unique name
Public Overrides ReadOnly Property EditorTypeName() As String
Get
Return MyGridLookUpEditName
End Get
End Property
'Register the editor
Public Shared Sub RegisterMyGridLookUpEdit()
'Icon representing the editor within a container editor's Designer
Dim img As Image = Nothing
EditorRegistrationInfo.Default.Editors.Add(New EditorClassInfo(MyGridLookUpEditName, _
GetType(MyGridLookUpEdit), GetType(RepositoryItemMyGridLookUpEdit), _
GetType(GridLookUpEditBaseViewInfo), New ButtonEditPainter, True, img))
End Sub
'Override the Assign method
Public Overrides Sub Assign(ByVal item As RepositoryItem)
BeginUpdate()
Try
MyBase.Assign(item)
Dim source As RepositoryItemMyGridLookUpEdit = _
CType(item, RepositoryItemMyGridLookUpEdit)
If source Is Nothing Then Return
Finally
EndUpdate()
End Try
End Sub
End Class
Public Class MyGridLookUpEdit
Inherits GridLookUpEdit
'The static constructor which calls the registration method
Shared Sub New()
RepositoryItemMyGridLookUpEdit.RegisterMyGridLookUpEdit()
End Sub
'Return the unique name
Public Overrides ReadOnly Property EditorTypeName() As String
Get
Return RepositoryItemMyGridLookUpEdit.MyGridLookUpEditName
End Get
End Property
'Override the Properties property
'Simply type-cast the object to the custom repository item type
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public Shadows ReadOnly Property Properties() As RepositoryItemMyGridLookUpEdit
Get
Return CType(MyBase.Properties, RepositoryItemMyGridLookUpEdit)
End Get
End Property
End Class
This example customizes the GridLookUpEdit to create a data-bound image combobox.
Show 15 items
Object MarshalByRefObject Component Control DevExpress.XtraEditors.XtraControl ControlBase BaseControl BaseEdit TextEdit ButtonEdit PopupBaseEdit PopupBaseAutoSearchEdit LookUpEditBase GridLookUpEditBase GridLookUpEdit
See Also