For those of you who attended my Oct. 23, 2007, 6:00pm presentation (and even those of you who didn't) on Windows Presentation Foundation with a focus on XAML and the Provider Model, I promised to put some links up for your reference.
I'm trying to upload the actual PowerPoint presentation , but I don't think the GWB upload tool likes pptx's, or zip files for that matter.
To give a brief description of presentation I gave, I talked about WPF, XAML, code-behind (using C#) and the Provider Model.
WPF
WPF is Microsoft's new way of designing user interfaces. Period. It uses XAML, which is an XML-based way of marking up a UI. If you're using VS 2005, you can download the .net 3.0 and Silverlight extensions and you'll be able to work in WPF (although you won't have the neat tools that are coming out in VS 2008, link below)
Several tools render XAML, most notably Microsoft Expression Blend, which is a really neat way to allow GUI designers and hard-core developers to collaborate.
XAML uses DirectX, which means it takes full advantage of your graphics card, as opposed to having your CPU handle all of the software rendering.
Provider Model
The provider model is a formal, standard solution to a common software problem. For example, if you have an app that needs to access data from Access, XML, TXT, SQL 7 or SQL 2005, you'd typically have to write all of that code, with many perils and twists and turns, throughout one class library. You may break it out into many classes or assemblies, but you're still faced with the problem (at the application level) of choosing which implementation to invoke. The provider model lets you inherit from ProviderBase, and you then implement your many derived classes, each one with a specific data-access task. You also need to implement a configuration settings module, and an interface, but that's about it. Then, in your hosted app.config file, you just set the provider you want to use, and your application uses it. If you want to switch, stop your app, change the config file, restart the app, and you're using a different implementation. This is great because you can create mock providers, which can isolate the provider and tell you if you're consuming what the provider is providing correctly. You can have multiple implementations, each one tested and stabile, and not have to worry about changing code when your business requirements change.
This is great, Doug. But how do I get started?
To get started with Microsoft Visual Studio 2008 Beta 2 (codenamed "Orcas"), go to the MSDN download site (link below). You can download different versions of the IDE (like Professional or Team Foundation Server), or you can download a VPC with WinXP and Orcas on the VHD. Beware, I've had a lot of problems with the VPC, and you're probably better off carving out some space on your machine (or making your own VPC for it) and downloading just the IDE. The link for these downloads is here.
Also, I talked about Bill Steele who is doing an 18-part series on WPF: Soup to Nuts. You can look at his MSDN blog, or you can register for upcoming webcasts. He's doing really *really* cool stuff with WPF and Silverlight.
One final thing that I mentioned was Charles Petzold's All XAML Clock. This is really cool. This is an animated analog clock, built entirely in XAML, with no code-behind. All of the UI stuff, as well as the events and triggers, is built entirely in markup. Rock on.
I think that's it for now. If I can upload the PowerPoint and some source code, I'll come back and update this blog.
UPDATE: the links to the presentation and demo solution are below.
Get the zipped version of the PowerPoint here.
Get the zipped version of the WPF Demo solution here.
As always, please let me know if you have any questions.
My oldest child, Katie, is 3. She absolutely loves playing on the computer, and she's starting to learn her ABC's and 123's. My wife and I get her set up on either Disney's, Sprout's or Noggin's (parents with young children know what I'm talking about) websites, but they just don't seem too navigable for kids, especially at Katie's age.
She just wants to point and click, without any real context as to what she is doing.
I thought I would take her love of computers (and mine too!), and my desire for her to learn, so I built an app called "Katie's Learning Wiindow" that would randomly display randomly colored letters or numbers on the screen, and provide her feedback when she clicks on one of them. Future iterations (perpetual BETA, baby!) of this app may pompt her to locate a letter or a number and reward her on a correct answer, but, considering I put an hour into this while my wife was at Wal-Mart, this is a pretty good V1.0 release.
Here's how it works (for the most part):
- A panel control on the window is loaded with a bunch of label controls of fixed width and height, and the label text is set to a fixed font size. Each label control effectively become a "cell" on the panel.
- By determining the width and height of the panel, I can calculate the number of horizontal and vertical cells that will fit in the space, and those cells are loaded into a 2-dimensional array.
- I either loop through a collection of random letters, or randomly select a number from 1 to [max], and add them to another collection, guaranteeing uniqueness as I add.
- I then randomly calculate the X and Y coordinates, finding a random cell in the "grid", if you will. I make sure there's not already a label control in there, and add a label control with the random character information to that cell in the array.
- Once I've looped through my collection of random letters (or I've reached my [max] number count), I add the label controls (and click event handlers) to the panel's Controls collection.
- To finish it all off, I added two buttons below the panel that switch between ALPHA and NUMERIC modes, and resets and redraws the label controls.
- When the form is resized, resize the panel control so that, on a subsequent click of either button, the number of cells on the panel and the random location of label controls in each cell is recalcuated.
Here's a screen cap of the application:
Here's the code (I like #regions):
BTW, this was built with Microsoft Visual Studio 2003. I haven't had a chance to install 2005 on my home PC yet. Instead of using Collections (like I did), you may want to use Generics to manage the objects in the code below.
#Region "-- Win32 API declaration --"
' declare the Win32 API call
Private Declare Auto Function PlaySound Lib "winmm.dll" _
(ByVal lpszSoundName As String, ByVal hModule As Integer, _
ByVal dwFlags As Integer) As Integer
#End Region
#Region "-- Private variables and Enums --"
Private collLabels As Collection
Private collColors As Collection
Private _displayMode As Integer
Private Enum CharacterTypes
ALPHA = 0
NUMERIC = 1
End Enum
#End Region
#Region "-- Constant declarations --"
Private Const SND_FILENAME As Integer = &H20000
Private Const ALPHABET As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Private Const FONT_SIZE As Int16 = 30
Private Const MAX_ALPHA_CHARS As Int16 = 26
Private Const MAX_NUMERIC_CHARS As Int16 = 30
Private Const ALPHA_CELL_WIDTH As Int16 = 48
Private Const ALPHA_CELL_HEIGHT As Int16 = 48
Private Const NUMERIC_CELL_WIDTH As Int16 = 96
Private Const NUMERIC_CELL_HEIGHT As Int16 = 48
#End Region
#Region "-- Window event handlers --"
#Region "-- LearningWindow_Load --"
Private Sub LearningWindow_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' instantiate the collections
collLabels = New Collection
collColors = New Collection
' add some colors to the colors collection
collColors.Add(System.Drawing.Color.Red)
collColors.Add(System.Drawing.Color.Blue)
collColors.Add(System.Drawing.Color.Green)
collColors.Add(System.Drawing.Color.Yellow)
RedrawLabels(CharacterTypes.ALPHA, MAX_ALPHA_CHARS)
End Sub
#End Region
#Region "-- Generic label click event handler --"
Private Sub LabelClick(ByVal sender As Object, ByVal e As EventArgs)
' UNCOMMENT THIS ONCE YOU HAVE SOME WAV FILES TO PLAY
'PlayWav(CType(sender, Label).Text & ".wav")
'MsgBox(CType(sender, Label).Text & " was clicked.")
End Sub
#End Region
#Region "-- LearningWindow_Resize --"
Private Sub LearningWindow_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
pnlMain.Width = Me.Width
pnlMain.Height = Me.Height - 120
btnAlphabet.Top = Me.Height - 64
btnNumeric.Top = Me.Height - 64
End Sub
#End Region
#Region "-- btnAlphabet_Click --"
Private Sub btnAlphabet_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAlphabet.Click
RedrawLabels(CharacterTypes.ALPHA, 26)
End Sub
#End Region
#Region "-- btnNumeric_Click --"
Private Sub btnNumeric_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNumeric.Click
RedrawLabels(CharacterTypes.NUMERIC, 30)
End Sub
#End Region
#Region "-- pnlMain_Click --"
Private Sub pnlMain_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles pnlMain.Click
' UNCOMMENT THE BELOW CODE ONCE YOU HAVE WAV FILES RECORDED
'If _displayMode = CharacterTypes.ALPHA Then
' PlayWav("click_a_letter.wav")
'ElseIf _displayMode = CharacterTypes.NUMERIC Then
' PlayWav("click_a_number.wav")
'End If
End Sub
#End Region
#End Region ' Window event handlers
#Region "-- RedrawLabels --"
Private Sub RedrawLabels(ByVal characterType As Integer, ByVal maxChars As Integer)
Dim cellWidth As Int16
Dim cellHeight As Int16
Dim character As String
Dim aCell As Cell
Dim bFound As Boolean = False
Dim panelWidth As Integer = pnlMain.Width
Dim panelHeight = pnlMain.Height
' set the module-level display mode for when it's used from other control event handlers
_displayMode = characterType
' set the desired cell width for ALPHA or NUMERIC characters
If characterType = CharacterTypes.ALPHA Then
cellWidth = ALPHA_CELL_WIDTH
cellHeight = ALPHA_CELL_HEIGHT
ElseIf characterType = CharacterTypes.NUMERIC Then
cellWidth = NUMERIC_CELL_WIDTH
cellHeight = NUMERIC_CELL_HEIGHT
End If
' determine how many "cells" will fit in the given screen size, rounded to the nearest integer
Dim hCells As Integer = panelWidth / cellWidth
Dim vCells As Integer = panelHeight / cellHeight
' prepare a 2-dimensional array to contain the cells
Dim arCells(hCells, vCells) As Cell
Dim randomCellX As Integer, randomCellY As Integer
' remove all labels from the panel
pnlMain.Controls.Clear()
collLabels = New Collection
' randomly add unique characters to the collection
While collLabels.Count < maxChars
bFound = False
Select Case characterType
Case CharacterTypes.ALPHA
' get a random letter
character = CType(ALPHABET.Substring(RandomNumber(0, (maxChars - 1)), 1), String)
Case CharacterTypes.NUMERIC
' get a random number
character = RandomNumber(1, maxChars)
End Select
' add the first character to the collection
If collLabels.Count = 0 Then collLabels.Add(character)
For lcvLabels As Integer = 1 To collLabels.Count
If collLabels.Item(lcvLabels) = character Then
bFound = True
Exit For
End If
Next
If Not bFound Then collLabels.Add(character)
End While
' randomly add characters to the "cells" in the array
For lcvCharacter As Integer = 1 To collLabels.Count
Do
' get random (X,Y) coordinates for placement in the array
randomCellX = RandomNumber(0, hCells - 2)
randomCellY = RandomNumber(0, vCells - 2)
If arCells(randomCellX, randomCellY) Is Nothing Then
' populate and add the cell at the random position in the array
aCell = New Cell
aCell.Left = randomCellX * cellWidth
aCell.Top = randomCellY * cellHeight
aCell.Character = collLabels(lcvCharacter)
arCells(randomCellX, randomCellY) = aCell
Exit Do
End If
Loop
Next
' now go through the array, build label controls, and add them to the panel in their appropriate cells
For lcvCellsX As Integer = 0 To hCells
For lcvCellsY As Integer = 0 To vCells
If Not arCells(lcvCellsX, lcvCellsY) Is Nothing Then
aCell = arCells(lcvCellsX, lcvCellsY)
lbl = New Label
Dim fnt As Font
Dim siz As Size
fnt = lbl.Font
siz = lbl.Size
lbl.Font = New Font(fnt.Name, FONT_SIZE, FontStyle.Bold)
lbl.Size = New Size(cellWidth, cellHeight)
lbl.ForeColor = collColors.Item(RandomNumber(1, collColors.Count))
lbl.Top = aCell.Top
lbl.Left = aCell.Left
lbl.Text = aCell.Character
lbl.Name = "lbl" & aCell.Character
pnlMain.Controls.Add(lbl)
AddHandler lbl.Click, AddressOf LabelClick
End If
Next
Next
End Sub
#End Region
#Region "-- Helper functions --"
#Region "-- PlayWav --"
Public Function PlayWav(ByVal fileFullPath As String) As Boolean
' this will look in the \bin directory for .wav files named 1.wav, or a.wav, etc. I hope you have a good recording voice.
' return true if successful, false if otherwise
Dim iRet As Integer = 0
Try
iRet = PlaySound(fileFullPath, 0, SND_FILENAME)
Catch
End Try
Return iRet
End Function
#End Region
#Region "-- RandomNumber --"
Public Function RandomNumber(ByVal low As Int32, ByVal high As Int32) As Integer
Static RandomNumGen As New System.Random
Return RandomNumGen.Next(low, high + 1)
End Function
#End Region
#End Region
End Class
#Region "-- Cell class --"
Friend Class Cell
Public Top As Integer
Public Left As Integer
Public Character As String
End Class
#End Region
Please feel free to contact me, or post a comment, if you have any questions on anything.
Doug