Avalon Adventures Part 3
NorthWind Avalon Part 3– Lists With Style
Code for this demo can be found in the downloads section of www.dashpoint.com
After figuring how to do simple data binding I set about working to create the “fully functional” NorthWind example. This example consists of 3 windows.
- A window containing all the customers and a button to open the customer entry screen.
- A window with customer information including a list of their orders. This form will include a button to open up an order.
- A window to display an order and its lineitems.
So the first form I created I called MainMenu. My goal on this form was to provide a grid of customer information that user could select a customer and then open a customer entry screen.
So I pinged Mr Anderson… Any grid controls in Avalon? Nope. You could probably use a list control to emulate what you want to do. Ok…. Here we Go!
To start with I created a new Window… I named it MainMenu. I added the Loaded attribute to the Window definition to insure that the OnLoaded event would be called.
Loaded="OnLoaded"
I then my grid I named it “CustomerFlow”, specified 1 column and 2 row definitions. The first row is 50 units high and the 2nd row takes up the remaining space on available to the form. The grid definition is as follows:
<Grid ID="CustomerFlow">
<RowDefinition Height="50" />
<RowDefinition Height="*" />
<ColumnDefinition Width="*"/>
</Grid>
The next items to add are a button and a list box. The button is used to open up the customer entry screen. The list box contains the list of our customers. I named the listbox “CustomerList” and placed each control into its respective row/column. Here’s the code.
<Button
Grid.Row="0"
Grid.Column="0" >
Open Customer Screen
</Button>
<ListBox
Grid.Row="1"
Grid.Column="0"
ID="CustomerList"/>
After adding the controls to the form I turned my sights to the Code Behind form. This is actually pretty simple. Here’s what I did….
- Added a DataSet property to the form
- Added a function called LoadCustomerList(). This function’s job is to retrieve the customer list from the data access layer, store that data in the property added in step 1 and to bind the customer data to the list box.
- In the OnLoaded Sub I called LoadCustomerList function.
Public CustomerData As DataSet
Private Sub OnLoaded(…)
Me.LoadCustomerList()
End Sub
Function LoadCustomerList() As Object
Me.CustomerData = DataAccess.GetCustomerList()
Me.CustomerFlow.DataContext = _
Me.CustomerData.Tables("customers")
End Function
As you can see the DataContext being specified here is that of the CustomerFlow object, this is the customer grid
If you recall, in Part 2 we set the DataContext of the Window itself. So what’s going on here? Well it’s actually pretty cool. Each object has ITS OWN DataContext property. In this case the DataContext we are manipulating is the one contained in the Grid class (aks CustomerFlow). What this means is we can have multiple separate data sources for each form all the way down to the control level. Awesome!
I then added the binding syntax to the list box. I want the contents of my table to be bound into the items collection of the list box I did this by adding the following attribute to my list box object
ItemsSource="*Bind()"
Now I was ready to test my form and see the data bound into my list box. This is what I saw:
Yup that’s not what the doctor ordered is it ?
The issue is that you need to tell the list box what columns you want to display and where. This is where you get style.
So I looked at examplex provided by Chris Sells’s papers and David Jenni to see what a style is all about. Basically a style is a way to change the display contents of an object in a generic manner.
So here’s the style for our list.
<Window.Resources>
<Style x:Name="CustomerStyle">
<Style.VisualTree>
<FlowPanel>
<Text Width="20%"
FontSize="14"
TextContent="*Bind(Path=customerid)"/>
<Text Width="30%"
FontSize="14"
TextContent="*Bind(Path=companyname)"/>
<Text Width="50%"
FontSize="14"
TextContent="*Bind(Path=city)"/>
</FlowPanel>
</Style.VisualTree>
</Style>
</Window.Resources>
Now that’s a whole lot of XAML. So here’s an explanation as best as I can see…
Styles are added to the Resources section of the Window. These are re-usable elements that can be applied to other elements at run time.
We added a <STYLE> element and named it CustomerStyle with the x:Name attribute. We specified the style as a VisualTree.
To be honest I don’t know why we chose this VisualTree style at all. I did this by mimicking the code from Sells and Jenni. Even reading the Avalon docs didn’t provide any real help. So we’ll take a Nike approach and “Just Do It!”
Next we added a flow control object which allows the controls to be properly resized when appropriate.
Finally we add the controls that will be used to display our data. You can manipulate the attributes for each control as you see fit. As you can see below we specified the font, size and the binding for each element.
<Text Width="20%"
FontSize="14"
TextContent="*Bind(Path=customerid)"/>
ANNOYANCE: One item to note here is that the Bind() syntax is Case Sensitive. This is a real pain. This means that when I add my bindings I need to make sure I am getting the correctly cased name from the query resultset. This binding mechanism needs to strip off it’s XML heritage and move into a case insensitive world.
Finally you need to apply your style to the list box. This is done with by setting the ItemStyle property.
ItemStyle="{CustomerStyle}"
The syntax for our listbox is now as follows:
<ListBox
Grid.Row="1"
Grid.Column="0"
ID="CustomerList"
ItemStyle="{CustomerStyle}"
ItemsSource="*Bind()"/>
And here’s a shot of our completed screen.
Ok that’s enough for this part. Next part I will show how we hook up events to the form.