« Context Menus | Index | Drag and Drop » |
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.
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.
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.
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
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).
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.
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()
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):
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.
The following sample will binds a list of Person objects to Better ListView:
C#
// create a list of Person objects
List<Person> persons = new List<Person>(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
« Context Menus | Index | Drag and Drop » |
Better ListView Documentation | Copyright © 2010-2012 ComponentOwl.com |