Pro WPF in C# 2008 Windows Presentation Foundation with .NET 3.5, Second Edition by  Matthew MacDonald

Contained herein is a collection of errata and comments on the MacDonald book. These comments are mine alone and are not endorsed or reviewed by APress or the books author.

General note: this book was written prior to the release of Windows 7. Most references to Windows Vista also apply to Windows 7. I'll make note of any Vista-Windows 7 differences below. As for the text, assume any reference to Vista also refers to Windows 7.

Introduction

Page Position on page comment or correction
xxix Note near top of page Windows 7 should also be included...as 32 bit and 64 bit OS versions. .Net applications run on either 32 or 64 bit where the JITter will compile to native 32 or 64 bit code.
xxix first pph after Note the sentence reads "In order to create a WPF 3.5 application....you need Visual Studio 2008..."
No, you can create .Net applications with notepad and the .Net release install (this includes the C# and VB compilers).  Visual Studio is a fine tool, but it is not a required tool to build .Net apps.
xxix second pph after Note This pph talks about Expression Blend (the current version is 3). This pph implies that Blend is a tool purely for designers...but I'll recommend that as a developer you should learn the basics of this tool. For instance, Blend can be used to emit standard control 'Control Templates' that are useful for extending your WPF knowledge.

 

Chapter 1 - Introduction WPF

Page Position on page comment or correction
2 first pph after first Note Reads "One component that's still in the picture....is User32".
Top level windows are HWND based windows, as are MessageBox instances and the two built-in dialogs (OpenFileDialog and SaveFileDialog; use Spy++ and see that the MessageBox, OpenFileDialog, and SaveFileDialog HWND class is #32770)
2 last sentence WPF can perform software emulation if the video driver/hardware is lacking, but keep in mind that some of these operations are VERY slow. You can see how this works by setting up a machine and use the standard VGA driver.
3,4 middle of page 3, top of page 4 "WPF Tiers"...see my simple sample: WPFhardwareTiers.zip (Note: this app will display the Tier level (0, 1, or 2) and will work with or without .Net 3.5 installed)
9 Middle to end of page

Here is what to do to change system DPI in Windows 7 (similar to Windows Vista)
1) right click desktop and choose Personalize
2) select Display from link on left
3) select Set custom text size (DPI)
Note: Windows 7 also supports Windows XP DPI Scaling as described in the instructions for Vista

12 bottom pph of page note that .Net 3.5 SP1 makes changes to primary .Net 2.0 types (for instance WaitHandle gets a new single parameter method overloads for WaitOne). This means that if you limit your project to .Net 2.0 and compile/test with .Net 3.5 SP1 applied might not run on a system with .Net 2.0 only installed). Also note that Visual Studio 2008 SP1 installs the .Net 3.5 SP1.
What is my point? To be sure to test on an OS with the minimum .Net runtime installed
13 last sentence of first pph reads "...(such as the WebBrowser control, the DataGridView control, and the HelpProvider component)"
You can setup simple HTTP rendering with the WPF Frame class, the DataGridView can be replaced with existing WPF controls or use of the Codeplex WPF Toolkit (see CodeProject: WPF DataGrid Practical Examples and Windows Forms Controls and Equivalent WPF Controls)
Refer to page 252 for some reasons why you might still wish to use the WinForm WebBrowser control.
Other controls that are missing: CalendarControl, DateTimePicker, NumericUpDown. Some missing common dialogs: ColorDialog and FontDialog
14 4th pph reads "...Silverlight that's designed to take a subset of the WPF platform..."
Silverlight is similar to WPF, but I would not call it a subset
14 2nd bullet item last sentence of the Silverlight 2.0 bullet reads "However, at the time of this writing it's still in beta".
Well, at the time of this writing, Silverlight 2.0 and 3.0 have been released.
17 Note at bottom of page The System.Windows.Forms namespace is mostly reserved for WinForms; WPF includes an assembly named WindowsFormsIntegration and includes the System.Windows.Forms.Integration namespace that is used for hosting WinForm controls within WPF
18 first sentence The STAThreadAttribute is required in WPF (unlike WinForms, where it is optional if you are avoiding use of COM services like drag-drop)
18 2nd pph reference to "...inherited default values..."
Win32 User and WinForms developers would know these as 'Ambient' properties
18 last sentence reads "UIElement also adds support for..." should read "FrameworkElement also adds support for..."

 

Chapter 2 - XAML

Page Position on page comment or correction
21 first pph Reads "..., its primary role in life is to construct WPF user interfaces".
I could not disagree more. XAML roll is to construct and initialize object hierarchies. It is currently used in WPF, Silverlight, Workflow, and XPS documents.
21 second pph Reads "It's unlikely that you'll write XAML by hand".
Again, I could not disagree more. The Visual Studio XAML designer is fine for quick demos and casual users. Writing markup is a necessity for production quality professional code development.
21 last sentence of note (bottom of page) Reads "...a whole host of tasks that are only possible - "
There exist a whole host of tasks only possible in code, but not in WPF XAML. It is certainly true that a number of tasks are much easier in XAML than in code. (disclaimer: in Silverlight there are tasks that can only be accomplished in XAML, but this is not the case in WPF)
22 last bullet item in note Reads "Currently, Visual Studio has no design-time support for crafting animations."
True, but Expression Blend has this support. And you can open your solutions in Blend as well as Visual Studio. In fact, you can have the same solution open simultaneously in Blend and Visual Studio (as long as you are careful to save edits as you switch between the two editing environments)
24 first section, top of page This section titled "The Variants of XAML" has a 3rd bullet item about Silverlight that says "...is a subset of WPF XAML". This is quite untrue. Silverlight and WPF are similar, but calling Silverlight a subset is misleading.
Also, the upcoming release of .Net 4 and Visual Studio 2010 is going to show more differences between these various technologies since XAML2009 with new enhancements will mostly be available only for Workflow. The XAML compiler provided in Visual Studio 2010 for WPF will be mostly the same as it is now.
24 last pph Reads "However, it is possible to use XAML without compiling it first"
This very much depends on what is in the XAML. For instance, specifying the x:Class attribute will require compiling. Also if you specify event handler hookups in XAML will also require compiling. Question: what compiler is used for XAML? Ask me for the answer
26 section XAML namespaces  the snippet of XAML code shows xmlns:x="http://...."
Technically, the xml prefix can be anything, but by convention the xaml namespace prefix is 'x'. If you are searching in the MSDN documentation for the definition of one of the xaml namespace attributes (say, x:Class, x:Type, x:Name, x:Uuid, or x:Null) then you search using the 'x' prefix and be sure to disable search filtering (for some odd reason, if you have the MSDN help viewer filtering on .Net you will not find these entries!!). See item below for page 45.
39 2nd to last pph Reads "The Grid displays all the controls it holds in an invisible layout of rows and columns..."
You can make this visible by setting the Grid attribute ShowGridLines = "true"
45 Tip this tip talks about commonly used namespace prefixes. You should also note that the 'x' prefix used for the XAML namespace is used in the documentation as well (see item above for page 26)
50 code snippet the author uses the LogicalTreeHelper class in this bit of code.  I'd like to point out that there is another helper class called the VisualTreeHelper. Here is a sample WPF application that will show the different output of these two helper classes. The application will use itself as the source of the visual or logical UI tree: DumpVisualAndLogicalTrees.zip
The logical tree is going to display the classes that you will (mostly) see when setting up a UI object heirarchy (the classes you use in XAML).
The visual tree is going to display the logical tree plus a bunch more...these 'extra' classes are introduced by the control/window/element templates. We discuss templates later in the course.

 

Chapter 3 - The Application

Page Position on page comment or correction
60 table on ShutdownMode enum values These modes are for top-level independent windows that are not setup with ownership (Window.Owner property)
61 table on application events the Startup event is said can be used to check command-line arguments. Sure, but you can obtain the command line arguments anytime later in the application lifetime simply by using the Environment.GetCommandLineArgs method
64 Handling Command-line Arguments see my note for page 61 above
73 side note on UAC some important additional information on manifest files and inclusion of the requestedPrivileges element
1) starting with Vista and later OS's, embedded manifests take precedence over external manifests (this is opposite to what XP/server 2003 does)
2) adding any form of the requestedPrivileges element will disable virtualization (a file system/registry feature added to Vista and later OS's). This is why one would add the asInvoker element since it is the default, but adding the element will disable virtualization. Another way to think about the requestedPrivileges element is this: when you add it to a manifest you are claiming that the application is Vista/Win7 knowledgeable.

 

Chapter 4 - Layout

Page Position on page comment or correction
79 top pph this pph talks about some of the specialized objets derived from the abstract Panel class. The author lists InkCanvas as one of these. Problem is, InkCanvas is not derived from Panel or Canvas.
The only relationship InkCanvas has to Canvas is the class name happens to include the string: 'Canvas'.
80 note at top of page discusses the XAML designers behavior of affixing fixed Width and Height to controls as you drag/drop them on the designer (or double click the controls in the toolbox). The note suggests that you remove these fixed sized from your XAML, but note this: if you ever click on the controls within the designer to move or adjust them ...then the fixed Width and Height will be regenerated.
This is yet another reason why I avoid the designer and work with XAML directly.
82 note at top of page the note implies that attached properties (Grid.Row, Grid.Column, Canvas.Top, Canvas.Left, etc) are purely an container-child mechanism. As you will see later this is not the case.
For panels, the specific panel defined attached properties work only with contained children.
82 last sentence before Alignment section heading reads: "...don't give you the ablitity to explicitly position elements".
You can explicity postion elements within the Grid panel by using a combination of the following FrameworkElement properties of the children: Margin, VerticalAlignment and HorizontalAlignment
82 2nd ppt under Alignment section heading reads "...is Left for label and Stretch for a Button."
This is incorrect. The default HorizontalAlignment is the same for Label and Button: Stretch.
I think the author is confusing the HorizontalContentAlignment where is is Left for Label (the content positions to the left and top for Label controls and center for Button controls)
82 note at bottom of page author says that StackPanel has a VerticalAlignment and HorizontalAlignment property...but this is a behavior of all Panel types (due to the fact that VerticalAlignment and HorizontalAlignment come from the base class of Panel: FrameworkElement).
So, the behavior the author speaks of in this note is for all panel types, not just StackPanel
83 Margin section author says that you can, in XAML, specify a Margin using a single value (for all four sides) and 4 values for (left, top, right, bottom).
You can also specify 2 values like so:
<Button Margin="10,20" Content="Press Me" />
The two value syntax means the 1st value is for left and right, the 2nd value is for top and bottom. So for this example: left and right are 10, top and bottom are 20
86 note on automatically sized windows last pph in note reads: "To enable automatic window sizing, remove the Height and Width properties....and set the Window.SizeToContent property..."
You do not have to remove Height and Width. When you set the SizeToContent property, the Height and/or Width will be ignored depending  the SizeToContent setting.
97-101 GridSplitter control info Note that the GridSplitter is a bit buggy. It has always been buggy and, unfortuneatly, will still be buggy in .Net 4.0.
See this link for more info on this problem: WPF GridSplitter randomly jumps when resizing | Microsoft Connect
106 Tip near top of page An interesting (and sometimes useful) feature of Canvas is this: you can absolutely position elements Canvas children (even at negative coordinates)  and then set the Canvas Width and Height to zero.
The result is a Canvas that disappears, but the 'child' controls remain at their relative offset positions from the upper left corner of the Canvas.
106 Z-Order section The author states that Canvas.ZIndex attached property can be used to affect Z order.
This is in error for WPF. The attached property in WPF is Panel.ZIndex not Canvas.ZIndex (the author is correct for Silverlight, by the way)
All references to Canvas.ZIndex or Canvas.SetZIndex or Canvas.GetZIndex should be changes to Panel.ZIndex and Panel.SetZIndex and Panel.GetZIndex

 

Chapter 5 - Content

Page Position on page comment or correction
121 pph near bottom of page starts with "In Chapter 4", 2nd sentence Reads: "Content controls use a compliemenatry property named Padding..."
All objects derived from the Control base class include Padding
125 sentence above section Programmatic Scrolling Reads: "... the HorizontalScrollBarVisibility property is Hidden by default..."
No, it is Disabled by default. If it were Hidden, then  you could use Home or End to scroll...but you can't

 

Chapter 6 - Dependency Properties and Routed Events

Page Position on page comment or correction
138 second pph, first sentence Reads: "Dependency properties are a WPF-specific creation"
Dependency properties are used in WPF, Silverlight, and Windows Workflow Foundation. So I would not call this a WPF-specific creation.
Note that WPF, Silverlight, and WWF each have their own implementation of dependency properties, but they are very similar in design and intent.
139 first sentence Reads: "..., because the DependencyObject class has no public constructor."
should read DependencyProperty and not DependencyObject. But this is not the whole reason...DependencyProperty is also a sealed class.
139 pph after first code snippet Reads "There are two steps involved in registering a dependency property. First, you create a FrameworkPropertyMetadata object..."
Note: there are 3 related classes for metadata: PropertyMetadata (the base class), UIPropertyMetadata, and FrameworkPropertyMetadata. Each class in this hierarchy adds more functionality. Use the one that makes sence for your property. In fact, there is no requirement to add metadata if none is required.
142 table item name: Inherits
This property is only valid for attached properties (DependencyProperty.RegisterAttached).
142-143 Property Change order of events (bullet items) The Validate callback will be called first, followed by the Coerce callback. If the Coerce callback changes the value (including returning UnsetValue), then the Validate callback will be invoked again.
Only if the target property actually changes will the Changed callback get invoked.
148 numbered list of dp precedence this is an abreviated list of dependency property value precedence. For the complete list see: Dependency Property Value Precedence
150 3rd from last pph, last sentence Reads: "...,both of which are defined in the base FrameworkElement class..."
No, the UIElement class defines AddHandler and RemoveHandler and RaiseEvent (even in Silverlight)
155 Note top of page Reads: "..., but an instance of the Page class"
Page cannot be a toplevel window (but using XAML it will appear to be top-level). The toplevel window in this case is NavigationWindow (a class derived from Window).
159 XAML snippet at bottom of page Reads: "<StackPanel Button.Click="..."
If you tried to type this out in XAML using Visual Studio XAML designer, you will find that the Intellisense will put ButtonBase.Click instead of Button.Click.
Either form will work (Intellisense knows that the Click event is actually defined on the abstract base class of Button: ButtonBase)...subject to the constraints listed in the note on top of the following page: 160
160 Note at top of page Setting up an attached event handerl to ButtonBase.Click or Buttton.Click or ToggleButton.Click will all do the same thing: Catch all Click events regardless of source.
(the author says otherwise, but testing confirms what I say above)
160 snippet near bottom of page using Tag property Note that Tag (of type Object) is for programmer use (it is not used by the system). It is defined on the FrameworkElement base class, so is available for all Control types.

 

Chapter 7 - Classic Controls

Page Position on page comment or correction
186 2nd pph of Font Inheritence section, 2nd to last sentence Reads: "You can't set the FontSize property for the StackPanel..."
Actually, you can specify the setting on this and any FrameworkElement derived class. Any class that does not expose a FontXXX related property and derives from FrameworkElement, then you can use an attached properties exposed by the TextElement class: TextElement.FontSize="20"

 

Chapter 8 - Windows

Page Position on page comment or correction
216 table on Window properties AllowsTransparency can only be set True if and only if WindowStyle is set to none (ie, no frame)
SizeToContent can be set in XAML along with Width and Height. At design time Width and Height take precedence, at runtime SizeToContent takes precedence upon first load and rederning (the user or code can change Width and Height thereafter)
NOTE: current (for .Net 2.0-3.5) there is no way to create a top level window that is Hidden. This capablity is to be available in .Net 4.0
218 last pph on page Reads: "Closing a window is equally easy, using the Close() method"
Ok, true, but modal windows probably should not be calling the Close method explicitly. Instead, modal windows would typically set the Window.DialogResult property to True or False. Why? Because this is the result handed back by the return of the ShowDialog() method. Setting this property will cause the modal to close while not setting the property and calling Close explicitly will send a 'false' back as a return value (in WinForms, the default return value would be 'Cancel' if Close was called).
Note that this is the same behavior that was part of WinForms modal Form. Big difference between WinForms and WPF: attempting to set the Window.DialogResult property on a modelss window will throw an exception in WPF.
You might wish to programmatically determin within your Window class implemenation if your window is running in modal or modelss mode. You can do this via the following code:
System.Windows.Interop.ComponentDispatcher.IsThreadModal property
NOTE: this property is not set during the Window construct or load. So, if you wish to know when the property is set, then handle the  System.Windows.Interop.ComponentDispatcher.EnterThreadModal event.
(Check out my note about page 225 below)
220 Discussion of the Settings tab

The author mentions the Settings tab and the Properties.Settings.Default static accessor for type safe access. Some things that the author does not say:
1) Application scope settings are read-only
2) User scope settings are read-write (see note below)
3) A number or data types shown are WinForm types and not WPF types (System.Drawing namespace types are all WinForms, not WPF. To use WPF types you need to browse for the System.Windows.Media namespace for the FontXXX types and Color. And use System.Windows namespace for Rect, Point, and Size)
4) Custom types can be added to this (but will probably require some WinForm programming if you need to add custom editors for your custom types)
5) You can reference settings from within XAML if you wish. See the following example that makes use of the Static markup extension: SettingsInXAMLdemo.zip

The User scope settings are read and write. This means that, in code, you can call Properties.Settings.Default.Save() to save changes or Properties.Settings.Default.Restore() to remove the changes. Note that, by default, these 'changes' are saved in a different config file that will be created under the current user profile (Vista/Win7 under \Users\<username>\AppData/Local\<app name>\;XP under \Documents and Settings\<username>\Local Settings\Application Data\<this process name>\

Also note that the default settings provider will keep a copy of user settings changes based on the current application absolute path (if another copy of the application is in another folder, then the saved changes will not be shared between these applications). You can replace the default settings provider so you can gain control of this mechanism if you wish.

225 The Dialog Model section, last pph bottom of page Reads: "You can take advantage of another shortcut."
Ok, but here are some issues you need to consider
1) setting DialogResult = true or false will close the dialog
2) setting DialogResult = null will not close the dialog
3) setting DialogResult to true, false, or null will cause an exception if the dialog was not shown modal
4) setting a button with IsDefault = true will not cause the DialogResult to be set true (contrary to the authors comment in this pph), nor will the Dialog close.
5) setting a button with IsCancel=true will cause the dialog to close when the button is clicked (the default DialogResult will be false). Note that the Click event handler will be called if you click the cancel button or you press the Esc key (but not if you press the "X" close button on the caption bar).
6) you can set DialogResult only once during the modal display of the dialog

Actually, I find in interesting that the Window.ShowDialog returns a nullable bool instead of a standard bool. As far as I can tell, ShowDialog always returns either True or False and never returns null. The Window.DialogResult property is a nullable bool, but the only way that the DialogResult will be null is if and only if the Window is displayed in modeless mode (and you access the DialogResult...it will be null)
(Check out my note about page 218 above)
227 last pph just before the Nonrectangular window section Reads: "You won't find any color pickers, font pickers, or folder browsers..."
You can use WinForm interop for ColorDialog and FolderBrowserDialog, but FontDialog is a bit tricky and probably not worth the effort to attempt to use via interop. Instead, you can use a WPF implemenation of FontDialog available via CodePlex: http://miniframework.codeplex.com/ and a SDK sample: Font Dialog Box Demo
232-233 general comment on moving/resizing windows this topic is also covered in chapter 15 "Control Templates", pp 486-488
235 1pph, 2nd sentence Reads: "...(which may require you to write a manifest, as described in Chapter 3)"
Visual Studio 2008 will , by default, provide an embedded manifest with the following settings:
 <requestedPrivileges>
    <requestedExecutionLevel level="asInvoker" uiAccess="false" />
 </requestedPrivileges>
This manifest will 'disable' virtualization for registry and file system. Also remember that starting with Vista and later OS's, internal manifests take precedence over external manifests.
243 Note top of page This note discribes issues with an older version of the SDK VistaBridge sample.
These issues are fixed in the latest Windows 7 SDK sample set.

 

Chapter 9 - Pages and Navigation

Page Position on page comment or correction
261 first code fragment text below fragement reads: "This code works no matter what..."
Yeah, I think this statement is a bit misleading. First of all, this code fragment will hand back null if executed within the Page or App or NavigationWindow constructor (the note does say this)
But keep in mind that it is a mistake to assume order of Load events within a nested UI. Just because the current WPF loader works inside out (most nested Load events fire before container events) might change in the future. I need to review this comment...certainly I can claim that this statement is misleading.

 

Chapter 10 - Commands

Page Position on page comment or correction
292 4th pph under heading The RoutedCommand Class Reads: "...implements the ICommand interface privatly and then adds..."
No, the ICommand interface is implemented explicity, not privately. You can still access the ICommand methods, you just need to explicity cast to ICommand to call them.
293 note at bottom of page another reason to not use the RoutedUICommand text: it does not support mnemonics (refer to p. 190 for mnemonics)
294 list of ApplicationCommands near bottom of page missing: NotACommand
This is useful for switching off a controls built-in InputBinding for a given command.
296 top of page code snippets show how you can use either
Command = "ApplicationCommands.New"  
or
Command = "New"
This short cut only works for the built-in commands (ApplicationCommands, NavigationCommands, EditingCommands, ComponentCommands, and MediaCommands). If you create your own custom commands, then you must fully qualify the names when you assign them to the Command parameter.

NOTE: you might find the following syntax in source code:
Command = "{x:Static ApplicaitonCommands.New}"
this will work, but takes more typing...as it turns out, there exists a TypeConverter for string to RoutedUICommand that allows the shorter syntax:
Command="ApplicationCommands.New" or Command="New"
and this same converter can be used for your custom commands (you just need the full type name)

 

Chapter 11 - Resources

Page Position on page comment or correction
325 last numeric item on page author states that an IOException is thrown if a satellite assembly is not found. I very much doubt this.
Satellite assemblies are optional. So on a multi-language OS where the user has changed the UI culture, then the .Net loader will attempt to probe to locate satellite assemblies. If a specific satellite is not found then it should default to the 'default' culture.
326 Preparing Markup Elements for Localization section note: the x:Uid attribute is the one exception to the rule: "XAML element-attribute nodes cannot specify attributes"
For example, take the following XAML fragment:
<Button>
  <Button.Content>
      ...stuff goes here
  </Button.Content>
</Button>
I had said that nodes where a '.' appears (such as <Button.Content>) cannot specify attributes. This is true except for the x:Uid attribute.
343 Note bottom of page Reads: "However, it's not acceptable to merge resource dictionaries that use the same resource names."
This is untrue (as demonstrated in my class). See: Merged Resource Dictionaries

 

Chapter 12 - Styles

Page Position on page comment or correction
     

 

Chapter 13 - Shapes, Transforms, and Brushes

Page Position on page comment or correction
370 Note, center of page last sentence reads: "Both these properties are initally set to use transparent brushes"
No, both Fill and Stroke are initially set to null brushes
373 first pph after note, about the fifth sentence Reads: "The Grid is a bit more flexible because it allows you to place as many elements as you want in the same cell (although it doesn't let you postion squres and ellipsis in different parts of that cell)"
Sure you can position shapes within a cell. Use a combination of Margin and VerticalAlignment/HorizontalAlignment to one or more of the edges
The point the author is attempting to make here is this: Canvas is the preferred container for vector graphics due to absolute postioning. Also remember that the Canvas Width and Height is not required to be non-zero to view Canvas children.
376 3rd pph down Reads: "However, consider what happens if you remove the Width and Height properties from the Canvas."
The description is a bit misleading I think. Remember that the Canvas can have zero Width and Height and the Canvas children will still display. But when you try to do this when the Canvas is a child of a Viewbox, you will see that the children, in fact, disappear.
This is happening because as the Canvas Width/Height tend to zero, this acts like a Zoom-in as the Viewbox attempts to scale up the child. The Canvas children disappear because the during the zoom-in, they move right off the lower right corner of the Viewbox. See my sample: Ch13p375_ResizeWithViewbox
377 top pph this pph discusses the Line shape and how it is positioned. I find Line a bit 'quirky' due mostly to it being derived from the Shape class. Line has a Width and Height (along with AcutalWidth, AcutalHeight), but these don't usually get used. To display a line you need to specify at the very minimum X2 and/or Y2 and Stroke.
The line origin (X1,Y1) is an offset from the upper left corner of the Line shape Width/Height.
Example:
Create us a demo WPF app using the Visual Studio project template. Create a single element in the supplied Grid like so:
<Line X1="100" Y1="100" X2="200" Y2="200" Stroke="Black" />
now add the following attributes for VerticalAlignment and HorizontalAlignment:
<Line X1="100" Y1="100" X2="200" Y2="200" Stroke="Black" VerticalAlignment="Center" HorizontalAlignment="Center" />
So, did the line center? No?? Well, what did center is the 'bounding rectangle' based on the Line origin of X1=0 Y1=0 and the supplied X2,Y2 in you XAML.
377 2nd pph You can use negative coordinates for a line, and use negative position information for any shape when positioning within a container (say, Canvas).
But I'd strike out most of what this pph says (about Margin, flow control, Vertical and Horiz alignment). Shape elements are a kind-of FrameworkElement...they all honor flow layout.
(for instance, check out what Expression Blend puts in your XAML file when you add Rectangles, Ellipse, or Line...but you will not see Line since Blend uses Path for everything except simple Rectangle and Ellipse)
385 last sentence Reads: "When you perform a series of transformations with the TransformGroup, WPF fuses your transforms together into a single MatrixTransform..."

You might have noticed by now that you cannot do simple arithmatic within XAML (addition, subtraction, multiplication). Well, actually you can if you really wish to. These transforms provide a means to express additons and multipications in XAML where you can extract result by accessing the MatrixTransform.Matrix properties: M11, M12, M21, M22 and OffsetX and OffsetY
387 last pph, middle sentence Reads: "Fortunately, WPF has a solution with the handy RenderTransformOrigin property, which is supported by all shapes"
Yes, this is true, but the description is very limiting. The RenderTransformOrigin property is defined in the UIElement class (the base class of FrameworkElement). Hence, it is available for almost every type you will be using in WPF: Controls, Panels, Shapes, etc
403 note bottom of page As of .Net 3.5 SP1, BitmapEffect is deprecated. Instead, you should be using Effects
Some addtional info: BitmapEffect is mostly software only supported (as far as I know). But BitmapEffects can be printed, Effects cannot.

 

Chapter 14 - Geometries, Drawings, and Visuals

Page Position on page comment or correction
416 note on page This discription of why Geomerty.Transform is different or perferred over FrameworkElement.LayoutTransform or UIElement.RenderTransform is a bit lacking, I think.
It would help to see a live example. So I changed my ShapeVsPath sample to add a ReadMe.txt file that will guide you through adding a ScaleTransform to a Path and then a Geometry so you can see the difference in behavior. To find the ShapeVsPath demo, check my class page under meeting 5 (note that I recently updated this sample on 1/14/2010)
Note that this sample also runs into an issue with a Freezable type that is actually frozen (we will be discussing Freezable in a later meeting)
420 first sentence under section Bezier Curves  Reads: "Bezier curves ... incorporates two control points..."
Cubic Bezier curves have two control points. Quadratic Bezier has one one. WPF supports both types of Bezier curves.
426-427 table 14-6 and 14-7 I am not one that should be ridiculing anyone's naming conventions, but I do need to point this out...
You might notice that there is a class called ImageDrawing and one called DrawingImage.
  1)  ImageDrawing is a Drawing that wraps a image (could be a bitmap). This cannot be rendered by itself.
  2) DrawingImage is ImageSource and allows you to host a Drawing inside of an Image element. This is used for rendering
434 first bullet, top of page Failure to call the AddVisualChild/AddLogicalChild methods will also break event / command routing
436 Tip Reads: "By setting the background to white (rather than transparent),.."
I think should be: "By setting the background to a non-null brush,..."
(where a SolidColorBrush with Colors.Transparent would be just as good a Colors.White wrt hit testing.)

 

Chapter 15 - Control Templates

Page Position on page comment or correction
451 2nd pph after Understanding Templates section, last sentence Reads: "That recipe is called a control template, and it's defined using a block of XAML markup"
Note that control templates can be written in code as well. XAML is not required to write a control template.
452 XAML snippet the snippet shows an element-attribute synatx for Boolean value settings. You could write your XAML this way if you wish, but it is usually written this way:
<Trigger Property="IsKeyboardFocused"
              Value="true">
       <Setter TargetName="Chrome"
                   Property="RenderDefaulted"
                   Value="true"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked"
              Value="true">
        <Setter TargetName="Chrome"
                    Property="RenderPressed"
                    Value="true"/>
</Trigger>
<Trigger Property="IsEnabled"
              Value="false">
         <Setter Property="Foreground"
                     Value="#ADADAD"/>
</Trigger>
455 2nd pph after Dissecting Controls section header, 1st sentence Reads: "The WPF documentation doesn't list the XAML for standard control templates."
True enough, but the XAML is available in two places:
a) Platform SDK WPF samples as all of the theme XAML files for standard controls
b) Expression Studio 3 has copies of the theme XAML files for standard controls
455 in same pph as listed above The author suggest that you can programmatically access a controls Template property and then use the XamlWriter class to dump it out.
If you do this, you will be missing a bulk of default styles including Brush definitions. The better approch is the one that I take in my DumpStandardControlStyle demo in meeting 4:
1) search for the standard control Style by using the following static resource search (example of looking for Button style):
    Style style = FindResource(typeof(Button)) as Style;
2) then dump the Style out using the XamlWriter class. You will find the ControlTemplate there along with a boat load of supporting Brushes, and default properties .
459 4th pph, last sentence  Reads: "...it's also a requirement, or the ContentPresenter won't work."
This is discussing the usage of TargetType in ControlTemplate. TargetType is not required for ContentPresenter. Here is a snippet:

<ControlTemplate TargetType="{x:Type Button}">
    <Border>
      <ContentPresenter Content="{TemplateBinding Content}" />
    </Border>
</ControlTemplate>

This can be rewritten as this if you wish:

<ControlTemplate>
    <Border>
      <ContentPresenter Content="{TemplateBinding ContentControl.Content}" />
    </Border>
</ControlTemplate>

You see, all the TargetType does is enable a more terse template definition (assuming you will have a lot more uses of TemplateBinding).

What the author is getting at is the following (and mentioned a few pages later in a note on page 461): the ContentPresenter has an implicit TemplateBinding to the ContentControl.Content property and you do not need to declare an explicit TemplateBinding for it ... if and only if you have a TargetType specified to a ContentControl or class derived from ContentControl like so:

<ControlTemplate TargetType="{x:Type Button}">
    <Border>
      <ContentPresenter  />
    </Border>
</ControlTemplate>
461 2nd sentence, first pph Author says that TemplateBinding can specify a Freezable source property.
Freezable class is the base of: Trigger, Timeline (Animations), Brush, Drawing, BitmapEffect and Effect, Geometry, GradientStop, ImageSource (Bitmaps and DrawingImage), MediaPlayer, Pen, plus more...but these are the important ones.
472 first pph after first code snippet The author describes a problem if a merged dictionary contains a key that may be defined within another merged dictionary.
But this is not a problem for either WPF or Sliverlight. I'm not sure what the author is worried about, but testing (and MSDN documentation) indicates that this is not an issue for merged dictionaries.
480 Note on page Reads: "The TemplatePart attribute indicates the name of the expected element (through the Name property) and its class (through the Type property). In Chapter 21..."
The error is that it is not chapter 21, but 24. Also I've got a few things to say about the reference to the class type:
Note that the class might be a base class, and the concrete class might be restricted. For instance, the TextBox (see base class TextBoxBase) has the following TemplatePartAttribute:
TemplatePart(Name="PART_ContentHost", Type=typeof(FrameworkElement))
but the type is actually restricted to ScrollViewer or Decorator or types derived from these two types.
(also note that the MSDN documentation is incorrect, it says ScrollViewer and AdornerDecorator but the code only restricts to ScrollViewer and Decorator)
As far as I know, the TemplatePartAttribute is purely a documentation element (there is no runtime or compile time enforcement or verifications)
486-487 general comment on entire page this page describes how to add code behind for sizing and moving a window. Note that this was also discussed on pages 232-233 of chapter 8 "Windows"

 

Chapter 16 - Data Binding

Page Position on page comment or correction
504 code snippet showing XAML Binding when setting a Binding Source to refer to a ResourceDictionary keyed value, you must use StaticResource and not DynamicResource like so:
Text="{Binding Source={StaticResource someResKey}..."
507 side bar on Designing Data Access Components, last sentence of first bullet item Reads: "One way to ensure the connection is closed at the appropriate time is with a using block"
First time I read this, I did not know what a 'using block' was...the author is referring to the using keyword and having the end of the using scope call Dispose for you automatically.
515 Note top of page you can also get a BindingExpression via the static BindingOperations class
515 last code snippet on page, showing call to OnPropertyChanged you should verify that the property is actually changing prior to calling PropertyChanged event. Also remember to call PropertyChanged event only after the property is changed (very important). The code should be rewritten like so:
set {
  if (unitCost != value)
  {
    unitCost = value;
    OnPropertyChanged(new PropertyChangedEventArgs("UnitCost"));
  }
}
516 table 16-4 DisplayMemberPath and ItemTemplate are mutually exclusive properties, only one can be specified
518 2 bullet item bottom of page An important point is missed in discussing ToString().
The use of ToString() acts like a onetime binding...no changes on the source will ever propagate to the target (even if you implement INotifyPropertyChanged)
521 first pph after Note, middle of page Reads: "You can derive a custom collection from ObservableCollection to customize the way it works, but that's not necessary"
I've seen implementations that do the following class inheritence (with absolutly no specialization or extensions):
public class PersonCollection : ObservableCollection<Person>
{
}
so that the PersonCollection can be referenced within XAML. XAML has issues with generic syntax.
535 two bullets, top of page I'd like to make this point very clear: a MultiBinding requires you to reference a Converter. You cannot create a MultiBinding element without the Converter attribute.

 

Chapter 17 - Data Templates, Data Views, and Providers

Page Position on page comment or correction
559 first bullet item on page Reads: "Data triggers work like the property triggers you learned about with styles in Chapter 12, except they don't require dependency properties"
I think this needs a bit of explaining.
A property trigger was written like so:
<Trigger Property="Control.IsMouseOver" Value="True">...
where the Property attribute must reference a dependency property.
On the other hand, a data trigger is written like so (instead of a Property attribute, you have a Binding attribute):
<DataTrigger Binding="{Binding Path=IsMale}" Value="False">...
the use of a Binding means that that source of the binding is not required to be a dependency property
NOTE: but in either case (Trigger or DataTrigger), the contained collection of Setter objects are restricted to dependency property targets.
561 code snippet, top of page instead of using FindResource, you might wish to use TryFindResource.
This is to keep the XAML designer happy since the DataTemplateSelector will be called during design time (before the ResourceDictionary is populated).
For an example of this problem, see the Windows WPF SDK sample: TabControlContentTemplateSelector. Compile it and then attempt to view the XAML designer for the main window. Now go the the window code-behind and change the two calls to FindResource to TryFindResouce...compile and view the XAML designer again.
The author then discusses a better approach, to make the DataTemplateSelector more XAML friendly. See my changes to this SDK sample in the meeting 6 sample TabControlContentTemplateSelector
564 code snippet bottom of page the following code is presented to demonstrate how to force a DataTemplateSelector to reevaluate on demand. Note that this code is specific to a ListBox:
DataTemplateSelector selector = lstProducts.ItemTemplateSelector;
lstProducts.ItemTemplateSelector = null;
lstProducts.ItemTemplateSelector = selector;
In my modified example from the SDK, TabControlContentTemplateSelector,  the following code was required:
object obj = tabCtrl1.SelectedItem;
tabCtrl1.ClearValue(TabControl.SelectedItemProperty);
tabCtrl1.SelectedItem = obj;
572 XAML snippet bottom of page Reads: Value="GoldenrodYellow" and should read Value="Goldenrod"
574 last buttet item on page Reads "If you data source doesn't implement IBindingList or IList but it implements IEnumerable, you get a basic CollectionView"
Actually, the implemenation you get back is an internal class instance called MS.Internal.Data.EnumerableCollectionView. But since you can only access the base class, CollectionView, then basically this statement is correct.
Also, there is a missing criteria in this list: If your data source implements ICollectionView, then you get a ItemCollection

 

Chapter 18 - Lists, Trees, Toolbars, and Menus

Page Position on page comment or correction
637 2nd to last pph on page Reads: "(In other words, there is a ToolBarItem class)."
Should read "(In other words, there is no ToolBarItem class)."
If you use Reflector, you might notice a ToolbarItem class (lower case 'b'), but this is an internal class used with UI Automation

 

Chapter 19 - Documents

Page Position on page comment or correction
     

 

Chapter 20 - Printing

Page Position on page comment or correction
     

 

Chapter 21 - Animation

Page Position on page comment or correction