Advanced Binding (to Business Objects)

  • 8 minutes to read

This topic describes the specifics of binding a lookup editor to a business object.

Unlike the standard lookup mode, which means that the editor's edit value is of a simple data type (e.g., integer), the binding of the lookup editor to a business object employs its own business object identification mechanism. This mechanism implies that a business object has a key field(s) that ensures object uniqueness. You must specify this key field name(s) using the RepositoryItemLookUpEditBase.KeyMember property.

The business object identification mechanism functions as follows. When the editor's dropdown is invoked showing the records of the lookup data source, the editor should find a match for its edit value (a business object) among the lookup records. A value(s) from the business object's key field(s) is obtained and compared with key field values of each lookup record. Once the match is found, it is highlighted in the dropdown.

When an end-user selects a certain lookup record in the dropdown, this record (the object that encapsulates this record) is assigned to the lookup editor's edit value. Ensure that the data type of lookup records is accepted by the editor's edit value.

lookup-businessobject-animation-editvalue.gif

The following properties need to be specified when binding a lookup editor to a business object:

For standalone lookup editors, these properties are available from the editor's Properties object (e.g., LookUpEdit.Properties). In-place lookup editors are presented by corresponding RepositoryItem class descendants - RepositoryItemLookUpEdit, RepositoryItemGridLookUpEdit, RepositoryItemSearchLookUpEdit and RepositoryItemTreeListLookUpEdit. Thus, the described properties are explicitly available.

Certain lookup editors may need additional customization (e.g., customize columns in the dropdown, specify the dropdown window's width and height, enable text editing, etc.). See the Lookup Editors and Main Settings topic and the LookUpEdit, GridLookUpEdit, SearchLookUpEdit and TreeListLookUpEdit class descriptions for more information.

For a standalone lookup editor, its edit value is specified by the BaseEdit.EditValue inherited property (this property is bindable). For an inplace editor, its value is provided by a cell in which the editor is embedded.

Example

Assume that you have two types of business objects (Product and Category), defined as follows:


public class Product {
    public Category Category { get; set; }
    public string ProductName { get; set; }
}

public class Category {
    public int ID { get; set; }
    public string Name { get; set; }
}

A Data Grid is bound to a list of Product business objects.


gridControl1.DataSource = new List<Product> {
    new Product(){ ProductName="Chang", Category = new Category() { ID = 0 } },
    new Product(){ ProductName="Ipoh Coffee", Category = new Category() { ID = 0 } },
    new Product(){ ProductName="Ravioli Angelo", Category = new Category() { ID = 1 } },
    new Product(){ ProductName="Filo Mix", Category = new Category() { ID = 1 } },
    new Product(){ ProductName="Tunnbröd", Category = new Category() { ID = 1 } },
    new Product(){ ProductName="Konbu", Category = new Category() { ID = 2 } },
    new Product(){ ProductName="Boston Crab Meat", Category = new Category() { ID = 2 } }
};

Note that the Category.Name field in the grid's data source may not even be initialized.

If you run the example without additional customization, the grid will look like the image below.

lookup-keymember-grid-nolookup.png

A lookup editor will be used to display category names in the Category column and allow an end-user to edit this column by selecting categories from a dropdown list.

All available categories are stored in the following list, which will be a lookup data source for the grid's inplace lookup editor (RepositoryItemLookUpEdit).


var categories = new List<Category> {
    new Category(){ ID = 0, Name = "Beverages" },
    new Category(){ ID = 1, Name = "Grains" },
    new Category(){ ID = 2, Name = "Seafood" },
};
//...

RepositoryItemLookUpEdit riLookUp = new RepositoryItemLookUpEdit();
gridControl1.RepositoryItems.Add(riLookUp);
riLookUp.DataSource = categories;

lookup-keymember-standalonelookupeditor.png

A lookup editor is assigned to the grid control's Category column. Thus, the editor's edit value will be a Category business object.


gridView.Columns["Category"].ColumnEdit = riLookUp;

To allow the lookup mechanism to find a match between the editor's value (a Category business object) and Category business objects in the lookup data source, a key field ("ID") is assigned to the RepositoryItemLookUpEditBase.KeyMember property.


riLookUp.KeyMember = "ID";

Now, the lookup mechanism is able to find a match by comparing the ID field value of the editor's bound business object with the ID field values in the lookup data source.

lookup-keymember-example-result.gif

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 Lookup_KeyMember {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            var categories = new List<Category> {
                new Category(){ ID = 0, Name = "Beverages" },
                new Category(){ ID = 1, Name = "Grains" },
                new Category(){ ID = 2, Name = "Seafood" },
            };

            gridControl1.DataSource = new List<Product> {
                new Product(){ ProductName="Chang", Category = new Category() { ID = 0 } },
                new Product(){ ProductName="Ipoh Coffee", Category = new Category() { ID = 0 } },
                new Product(){ ProductName="Ravioli Angelo", Category = new Category() { ID = 1 } },
                new Product(){ ProductName="Filo Mix", Category = new Category() { ID = 1 } },
                new Product(){ ProductName="Tunnbröd", Category = new Category() { ID = 1 } },
                new Product(){ ProductName="Konbu", Category = new Category() { ID = 2 } },
                new Product(){ ProductName="Boston Crab Meat", Category = new Category() { ID = 2 } }
            };

            RepositoryItemLookUpEdit riLookUp = new RepositoryItemLookUpEdit();
            riLookUp.KeyMember = "ID";
            riLookUp.DisplayMember = "Name";
            riLookUp.DataSource = categories;

            gridControl1.RepositoryItems.Add(riLookUp);
            gridView1.Columns["Category"].ColumnEdit = riLookUp;
        }
    }

    public class Product {
        public Category Category { get; set; }
        public string ProductName { get; set; }
    }

    public class Category {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}