Not your father's ListBox
[Edited: I changed the code to use one template this time to emphasize the proper use of styling. I also moved the the definition for the style to a class to make the code cleaner.]
After only a couple of days hacking away at WPF using the SDK docs and Google as reference, I may finally be gaining a toehold into the vast and exciting world of Avalon. So many things about WPF are new e.g. FrameworkElementFactory, DependencyProperty, DataTemplate and the list goes on. If you are not careful you'll loose yourself following the inheritance heirarchy.
I finally gave up doing that and decided that the best way to learn WPF was to leave all those fancy stuff first - like transformations, animation, 3D etc. - and work on the normal stuff like take some data from a service object and display the information on the screen. So to get the ball rolling, I whipped up a couple of rudimentary classes - Customer and CustomerService. After spending half a day pounding the keyboard, studying compiler error messages, checking the docs, googling, cursing - here's what i managed to do with the ListBox:

Although styling and templating are indisputably easier to accomplish in XAML, I believe programmers must also know how to do these things in pure code. Knowing how things are done under the hood will prove invaluable in the long haul. The days when Web developers would smirk at the sight of our user interfaces are about to end.
import System
import System.Windows
import System.Windows.Controls
import System.Windows.Controls.Primitives
import System.Windows.Data
import System.Windows.Documents
import System.Windows.Input
import System.Windows.Markup
import System.Windows.Media
import System.Windows.Navigation
import System.Windows.Shapes
import System.Globalization
class Customer:
[property(Name)] _name = ""
[property(Address)] _addr = ""
def constructor(name as string, addr as string):
_name = name
_addr = addr
override def ToString() as string:
return _name
class CustomerService:
static def GetCustomers():
yield Customer("brent","davao")
yield Customer("manny","gsc")
yield Customer("robert","cagayan")
yield Customer("george","cebu")
yield Customer("thomas","iloilo")
yield Customer("lelanie","tagum")
yield Customer("bong","digos")
yield Customer("hazel","bicol")
class CustomerTemplate(DataTemplate):
def constructor():
super(Customer)
panel = FrameworkElementFactory(StackPanel)
child1 = FrameworkElementFactory(TextBlock)
child1.SetValue(TextBlock.TextProperty, Binding("Name"))
child1.SetValue(TextBlock.FontSizeProperty, 20.0)
child2 = FrameworkElementFactory(Label)
child2.SetValue(Label.ContentProperty, Binding("Address"))
panel.AppendChild(child1)
panel.AppendChild(child2)
self.VisualTree = panel
class CustomerStyle(Style):
def constructor():
super(ListBoxItem)
setter1 = Setter(ListBoxItem.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch)
setter2 = Setter(ListBoxItem.MarginProperty, Thickness(2))
setter3 = Setter(ListBoxItem.BorderThicknessProperty, Thickness(1))
setter4 = Setter(ListBox.BorderBrushProperty, Brushes.Gold)
setter5 = Setter(ListBox.BackgroundProperty, Brushes.Bisque)
setter6 = Setter(TextBlock.ForegroundProperty, Brushes.Orange)
self.Setters.Add(setter1)
self.Setters.Add(setter2)
self.Setters.Add(setter3)
self.Setters.Add(setter4)
self.Setters.Add(setter5)
self.Setters.Add(setter6)
class Home(Grid):
def constructor():
self.ColumnDefinitions.Add(ColumnDefinition(Width:GridLength(200.0)))
self.ColumnDefinitions.Add(ColumnDefinition(Width:GridLength(10.0)))
self.ColumnDefinitions.Add(ColumnDefinition(Width:GridLength(400.0)))
self.RowDefinitions.Add(RowDefinition(Height:GridLength(20.0)))
self.RowDefinitions.Add(RowDefinition(Height:GridLength(100.0)))
self.RowDefinitions.Add(RowDefinition(Height:GridLength(10.0)))
self.RowDefinitions.Add(RowDefinition(Height:GridLength(100.0)))
self.RowDefinitions.Add(RowDefinition(Height:GridLength(10.0)))
self.RowDefinitions.Add(RowDefinition(Height:GridLength(200.0)))
self.RowDefinitions.Add(RowDefinition(Height:GridLength(10.0)))
regularListBox = ListBox()
regularListBox.ItemsSource = CustomerService.GetCustomers()
Grid.SetColumn(regularListBox,2)
Grid.SetRow(regularListBox,1)
templatedListBox = ListBox()
templatedListBox.ItemTemplate = CustomerTemplate()
templatedListBox.ItemsSource = CustomerService.GetCustomers()
Grid.SetColumn(templatedListBox,2)
Grid.SetRow(templatedListBox,3)
styledListBox = ListBox()
styledListBox.ItemContainerStyle = CustomerStyle()
styledListBox.ItemTemplate = CustomerTemplate()
styledListBox.ItemsSource = CustomerService.GetCustomers()
Grid.SetColumn(styledListBox,2)
Grid.SetRow(styledListBox,5)
text1 = TextBlock(Run("A Regular ListBox "))
text1.FontSize = 14
text1.HorizontalAlignment = HorizontalAlignment.Right
text2 = TextBlock(Run("A Templated ListBox "))
text2.FontSize = 14
text2.HorizontalAlignment = HorizontalAlignment.Right
text3 = TextBlock(Run("A Styled Templated ListBox "))
text3.FontSize = 14
text3.HorizontalAlignment = HorizontalAlignment.Right
Grid.SetRow(text1,1)
Grid.SetRow(text2,3)
Grid.SetRow(text3,5)
self.Children.Add(regularListBox)
self.Children.Add(templatedListBox)
self.Children.Add(styledListBox)
self.Children.Add(text1)
self.Children.Add(text2)
self.Children.Add(text3)
[STAThread]
def Main():
# define main window
win = Window(Title:"ListBox Demo")
win.Content = Home()
# define application
app = Application()
app.Startup += { win.Show() }
app.Run()