XTab's Blog

Ged Mead's Blog at vbCity

vbCity Blogs moved to:
http://cs.vbcity.com/blogs
  Home :: Syndication  :: Login

AprMay 2013Jun
SMTWTFS
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

Archives

Topics

Ramblings

VB.NET

In a previous Blog, I showed how to databind an XML file to a WPF ListView. As some people are more comfortable with collections of objects than they are with XML, in this blog item I thought we could look at binding to a collection.

One difference to note is that if you use XML data and XPath, you have the benefit of seeing all the data in the Design Pane at design time. With this collection of objects approach, the data is being created on the fly, so of course it can't be seen at design time because it doesn't exist. It isn't usually a problem, but if you have become used to seeing the data at design time, this can be disconcerting at first.

Creating a Collection of Objects
Constructing a class that you can use to create objects is exactly the same as with Windows Forms. Here is a simple class named DrinkProduct:

Public Class DrinkProduct

 

    Sub New(ByVal ProductID As String, ByVal ProductName As String, ByVal PackageType As String)

        Me.ProductID = ProductID

        Me.ProductName = ProductName

        Me.PackageType = PackageType

    End Sub

 

    Private _ProductID As String

    Public Property ProductID() As String

        Get

            Return _ProductID

        End Get

        Set(ByVal value As String)

            _ProductID = value

        End Set

    End Property

 

    Private _ProductName As String

    Public Property ProductName() As String

        Get

            Return _ProductName

        End Get

        Set(ByVal value As String)

            _ProductName = value

        End Set

    End Property

 

    Private _PackageType As String

    Public Property PackageType() As String

        Get

            Return _PackageType

        End Get

        Set(ByVal value As String)

            _PackageType = value

        End Set

    End Property

 

End Class

The next step is to create a collection of DrinkProduct objects. Again, there is nothing new here:

    Public Function StockCheck() As List(Of DrinkProduct)

        Dim CurrentProducts As New List(Of DrinkProduct)

        With CurrentProducts

            .Add(New DrinkProduct("CF1kg", "Instant Coffee", "1 Kg"))

            .Add(New DrinkProduct("CFG500g", "Ground Coffee", "500 g"))

            .Add(New DrinkProduct("Te500g", "Tea", "500 g"))

            .Add(New DrinkProduct("SMlk1lt", "Skimmed Milk", "1 Litre"))

            .Add(New DrinkProduct("HiJ300g", "HiJuice Drink Mix", "300 g"))

        End With

 

        Return CurrentProducts

    End Function

Where you place the above function is a matter of choice, depending on what kind of scope you want it to have within the application. I've chosen to place it in a helper module named modStockControl so that it is available application wide.

The next step includes a small change. The link between that collection of objects and the ListView that will display them in will be a DataContext. This is very much like the DataSource object that you will be familiar with from Windows Forms. In the code-behind for the Window, insert the following code:

    Dim CurrentProducts As New List(Of DrinkProduct)

 

    Private Sub Part2_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        CurrentProducts = StockCheck()

        ProductsListView.DataContext = CurrentProducts

    End Sub

Clearly, all this does is create an empty List, then generates some data to populate the List. The final line sets the DataContext of the ListView specifically to be the that List. At the risk of confusing the issue at this early stage, it isn't necessary to bind directly to the ListView. I could have set the DataContext on the Window or the Grid, for example and it may still be accessible by the ListView. This is something I will cover in a future blog.

Let's turn our attention to the ListView markup. A skeleton version is:

    <ListView Name="ProductsListView"

         ItemsSource="{Binding}">

      <ListView.View>

        <GridView>

          <!-- Product ID -->

          <GridViewColumn

         Header="ProductID" >

            <GridViewColumn.CellTemplate>

              <DataTemplate>

              <TextBlock Text="{Binding Path=ProductID}" />

              </DataTemplate>

            </GridViewColumn.CellTemplate>

          </GridViewColumn>

 

        <!-- Remaining two columns removed for brevity -->

 

        </GridView>

      </ListView.View>

    </ListView>

As you can see in the markup, the ListView is named and this name is the one we used in the code-behind to link to the DataContext. Even more crucially, the ItemsSource property is set to point to that same DataContext. Even though it only contains the word "Binding", WPF is smart enough to work out which particular binding is the appropriate one. So those two properties are the glue that enables the ListView to be populated with DrinkProduct objects.

The remaining markup creates a View and in that View there are three GridViewColumns (although I have only shown the markup for the first one). Inside the GridViewColumn markup you see a CellTemplate and a DataTemplate, both of which are simply devices for packaging the look of the data. In this case, a basic TextBlock is used to house the text data.

The line of markup:

 <TextBlock Text="{Binding Path=ProductID}" />

is the final piece of the Binding puzzle. The pointer to the "Binding" ensures that WPF looks back up the tree to find the source of the data that has been set. (In this case, it looks no further than the ItemsSource which in turn knows that the data will come from that collection of DrinkProduct items.)

The Path identifies the exact field in the data source that is to be bound to this column. For this column it is the ProductID field.

So, as you can see from the few steps we have taken above, data binding the ListView to a data source is a trivial task.

At the moment, the GUI isn't too impressive, because I've stripped out everything but the basics:

   

I originally intended to look at several other tweaks that you can make to the look and layout of WPF ListViews. But to keep this blog to a reasonable length (and so as not to confuse the data binding technique with other peripheral stuff) I'll cover that in my next blog.

posted on Friday, August 28, 2009 3:22 PM