# Data Binding

Better Thumbnail Browser for .NET (C#, VB) - Image thumbnail viewing and loading control
Download More Info

Better ListView supports both lookup binding and complex binding of user-provided data.

Complex binding allows you use any list-type collection (implementing IList or IListSource) to the control. Complex binding is not a feature of all WinForms controls.

Regular .NET ListView does not support binding of lists.

Lookup binding is supported on any WinForms control automatically, so we won't cover the topic here.

## Basic Data Binding

To bind a custom IList instance, set the DataSource property:

C#

    listView.DataSource = myList;  // myList is of type List<Person>

Visual Basic

    ListView.DataSource = myList  ' myList is of type List(Of Person)()

This fills Better ListView with objects in myList:

When converting Person objects to items, Better ListView first looks if there is a TypeConverter defined to use ConvertToString method. If not, standard ToString method is called to obtain item text.

## Displaying Custom Properties

To display value of some specific property of the bound object, use the DisplayMember property. For example, if we set the DisplayMember to "Age", Better ListView will represent each Person object by its Age property:

The DisplayMember property can be set on columns as well, so that each column can display another property of the bound object.

## Working with Values instead of Items

Each column in Better ListView can represent different property of the bound object. The property can be specified using ValueMember property (also on each column using BetterListViewColumnHeader.ValueMember). When specified, the property value can be accessed using the BetterListViewItem.Value (BetterListViewSubItem.Value).

For example, if we set ValueMember to "Age", each item will have the Value property set to corresponding short with the person's age.

You can also use following properties to work with selection in terms of the bound objects (values):

- SelectedValue

- SelectedValues

## Binding Columns

It is possible to display object properties in columns simply by setting DataBindColumns to true. This will cause Better ListView to generate column for each public property of provided list item type automatically:

Here the List<Person> object is bound. The Person type contains three public properties:

- Name (String)

- Age (short)

- Gender (enum of type PersonGender)

Column header texts are generated from property names. DisplayNameAttribute can be used on the property to specify custom name (as used in the Age column).

## Binding Position

Data binding mechanism in WinForms keeps information about current position in the bound list. Better ListView synchronizes current position with its selection.

To turn off this behvior, set DataBindPosition property to false. In this case, Better ListView selection will be independent on current position in the bound list.

## Sorting Items

Item sorting can be a nontrivial update of the bound list (which is unsupported by the standard data binding mechanism).

SortVirtual property should be set to true to turn off physical update of the Items collection. The columns will still display sort glyphs and the SortList will contain new sort state information, so the manual sorting is possible.

For example, if we have Person[] array bound, we can sort it manually in the AfterItemSort event handler this way:

C#

    // get values from the data source
    Person[] values = (Person[])this.listView.DataSource;

    // get listview items as keys
    BetterListViewItem[] keys = new BetterListViewItem[values.Length];

    this.listView.Items.CopyTo(keys, 0);

    // create custom comparer
    BetterListViewItemComparer comparer = this.listView.ItemComparer;

    comparer.SetSortList(this.listView.SortList, this.listView.Columns, true);

    // sort the data
    Array.Sort(keys, values, comparer);

    // refresh view
    ((CurrencyManager)this.listView.BindingContext[this.listView.DataSource]).Refresh();

Visual Basic

    ' get values from the data source
    Dim values As Person() = DirectCast(Me.ListView.DataSource, Person())

    ' get listview items as keys
    Dim keys As BetterListViewItem() = New BetterListViewItem(values.Length - 1) {}

    Me.ListView.Items.CopyTo(keys, 0)

    ' create custom comparer
    Dim comparer As BetterListViewItemComparer = Me.ListView.ItemComparer

    comparer.SetSortList(Me.ListView.SortList, Me.ListView.Columns, True)

    ' sort the data
    Array.Sort(keys, values, comparer)

    ' refresh view
    DirectCast(Me.ListView.BindingContext(Me.ListView.DataSource), CurrencyManager).Refresh()

Sorting can also be achieved by using DataTable, DataView or other type that supports sorting while bound to a control (such types implement IBindingList) as a data source:

C#

    // get data source
    DataTable dataTable = (DataTable)this.listView.DataSource;

    // set sort
    dataTable.DefaultView.Sort = "Name ASC, Age DESC";

    // refresh view
    (((CurrencyManager)this.listView.BindingContext[this.listView.DataSource]).Refresh();

Visual Basic

    ' get data source
    Dim dataTable As DataTable = DirectCast(Me.ListView.DataSource, DataTable)

    ' set sort
    dataTable.DefaultView.Sort = "Name ASC, Age DESC"

    ' refresh view
    DirectCast(Me.ListView.BindingContext(Me.ListView.DataSource), CurrencyManager).Refresh()

## Sorting by Value

Items can be sorted by other than displayed value when ValueMember property is set.

For example, we have a DataTable with columns "PercentDone" - which contains numeric values - and "PercentDoneDisplay" which contains corresponding values for display (e.g. rounded, with percent sign). Setting DisplayMember property on the column for percentage to "PercentDoneDisplay" and ValueMember property to "PercentDone" causes sorting according to value in numeric column.

Values are used for sorting only when the Key property of a sub-item is not available. The Key property has the highest priority when sorting, then the Value property, and then the Text property.

Following image shows multi-column sorting of a bound DataTable - the table is sorted according to column with aspect ratio enumeration (invisible, showing another column with display values) and a numeric column (percentage):

## Reordering Items and Columns

When some data is bound to Better ListView and columns are reordered, the control automatically performs refresh of the data (this is the case of ColumnReorderMode set to Enabled).

Automatic item reordering is restricted to happen on the same item level or between different levels, but only when none of the levels are the top level.

Item reordering with data binding should be implemented in the similar manner as item sorting. First, set the ItemReorderMode property to Custom. Then implement the custom reordering logic on data source in the AfterItemReorder event handler.

## Sample Source Code

The following sample will binds a list of Person objects to Better ListView:

C#

    // create a list of Person objects
    List&lt;Person&gt; persons = new List&lt;Person&gt;(new[]
                                            {
                                                new Person("Lee Adama", 45),
                                                new Person("Sally Gordon", 26),
                                                new Person("John Grant", 18),
                                                new Person("Susan Hutchinson", 37)
                                            });

    // create columns automatically
    this.listView.DataBindColumns = true;

    // populate ListView with our data
    this.listView.DataSource = persons;

Visual Basic

    ' create a list of Person objects
    Dim persons As New List(Of Person)(
        New Person() { _
                         New Person("Lee Adama", 45),
                         New Person("Sally Gordon", 26),
                         New Person("John Grant", 18),
                         New Person("Susan Hutchinson", 37)
                     })

    ' create columns automatically
    ListView.DataBindColumns = True

    ' populate ListView with our data
    ListView.DataSource = persons

The Person class itself is particularly simple - it does not need to provide anything else than public properties which are bound:

C#

    /// <summary>
    ///   Represents a simple data object (a person).
    /// </summary>
    internal sealed class Person
    {
        /// <summary>
        ///   Gets or sets the name of the person.
        /// </summary>
        /// <value>
        ///   The name of the person.
        /// </value>
        public string Name
        {
            get;
            set;
        }

        /// <summary>
        ///   Gets or sets the age of the person.
        /// </summary>
        /// <value>
        ///   The age of the person.
        /// </value>
        public int Age
        {
            get;
            set;
        }

        /// <summary>
        ///   Initializes a new instance of the <see cref = "Person" /> class.
        /// </summary>
        /// <param name = "name">The name of the person.</param>
        /// <param name = "age">The age of the person.</param>
        public Person(string name, int age)
        {
            Name = name;
            Age = age;
        }
    }

Visual Basic

    ''' <summary>
    '''   Represents a simple data object (a person).
    ''' </summary>
    Friend NotInheritable Class Person

        ''' <summary>
        '''   Gets or sets the name of the person.
        ''' </summary>
        ''' <value>
        '''   The name of the person.
        ''' </value>
        Public Property Name() As String
            Get
                Return _mName
            End Get
            Set(ByVal value As String)
                _mName = value
            End Set
        End Property

        ''' <summary>
        '''   Gets or sets the age of the person.
        ''' </summary>
        ''' <value>
        '''   The age of the person.
        ''' </value>
        Public Property Age() As Integer
            Get
                Return _mAge
            End Get
            Set(ByVal value As Integer)
                _mAge = value
            End Set
        End Property

        Private _mName As String
        Private _mAge As Integer

        ''' <summary>
        '''   Initializes a new instance of the <see cref = "Person" /> class.
        ''' </summary>
        ''' <param name = "Name">The name of the person.</param>
        ''' <param name = "Age">The age of the person.</param>
        Public Sub New(ByVal Name As String, ByVal Age As Integer)
            Me.Name = Name
            Me.Age = Age
        End Sub

    End Class

Better Thumbnail Browser for .NET (C#, VB) - Image thumbnail viewing and loading control
Download More Info