{{{{{

If you feel strongly that curly braces are best lined up in a particular style, then I have to wonder if you view code more at a low level than at a high level.

At a higher level, code could be thought of as assemblies made up of classes with statics, fields, methods, properties, and events. Curly braces are not very relevant at that level.

Quality code design happens at higher levels, not at curly braces level. Coding and design are usually inseparable at all but the most disciplined companies. Maintaining that higher-level focus while coding will yield better design.

Inconsistent curly braces or other syntactic styling, however, will distract other developers from the higher-level aspects of code, causing them to see the syntax before they see the higher-level constructs such as method, property, and class design.

Most good, experienced developers can get used to any team’s style rules in a week or two, no matter how illogical the rules may be.

Be consistent, and let those curly braces drift into the background.

}}}}}}

After reading about various ways of using the Silverlight Toolkit (http://silverlight.codeplex.com/) for Windows Phone 7 development, I gave up and tried a different approach.

I am using Windows Phone Developer Tools CTP – April Refresh, which you can download here: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=cabcd5ed-7dfc-4731-9d7e-3220603cad14

Instead of including Silverlight Toolkit dlls in my Windows Phone 7 Silverlight project, I included only specific source files that I needed. It worked without too much trouble, so unless you need a bunch of controls from the Silverlight Toolkit, I would recommend this simple approach for the DockPanel and WrapPanel controls. I suspect that it will also work for other simple controls.

1. Add a new class-library project to your Windows Phone 7 solution.

2. Add a reference to Microsoft.Phone.

Controls. Your reference list should now include the following: Microsoft.Phone.Controls, mscorlib, system, System.Core, System.Net, System.Windows, and System.Xml. Not all of those may be needed, but they were included by default.

3. Go to http://silverlight.codeplex.com, then switch to the Download tab. At the right, you’ll see a box called Other Downloads. Find the Silverlight 3 Toolkit November 2009 Stable release. Download and install it. (I did not try the April 2010 release because I had been told that not all Silverlight 4 classes will work for Windows Phone 7. Let me know if you succeed with the April 2010 release for Silverlight 4.)

4. Find the source code that you just installed. On my Vista system, I found it here: C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Toolkit\Nov09\Source.

5. Drag/drop the following source files to your newly created class-library project: Dock.cs, DockPanel.cs, LengthConverter.cs, NumericExtensions.cs, OrientedSize.cs, TypeConverters.cs, and WrapPanel.cs.

6. Also drag Resources.Designer.cs and Resources.resx from the Controls.Toolkit\Properties project to your new project. Once they are in your project, drag/drop them into the Properties sub-folder of your project. In that sub-folder, you should now see three files: AssemblyInfo.cs, Resources.Designer.cs, and Resources.resx.

7. Build it. If it all went well, include this project with any of your other projects that need DockPanel or WrapPanel.

8. Please tell me if these steps worked for you!

Thanks,

Dale Barnard

Most WPF developers know about the visual and logical trees of WPF. For example, a StackPanel with a Button may be made up of a StackPanel, Button, a ButtonChrome, a ContentPresenter, and a TextBlock. That’s the actual visual tree, but the logical tree is simply a StackPanel with a Button.

If you only specify your visuals in XAML, you may be overlooking another important control hierarchy. Consider this XAML:

<TabControl>
<TabItem Header=”Tab 1″>
<TextBlock Text=”This is on Tab 1″ />
</TabItem>
<TabItem Header=”Tab 2″>
<TextBlock Text=”This is on Tab 2″ />
</TabItem>
</TabControl>

The hierarchy shows that a TabControl has two TabItem controls, each with a TextBlock. This implies that the TabControl owns the TabItem controls, and each TabItem owns a TextBlock. Consider this code:

TabControl myTabControl = new TabControl();
TabItem myTabItem1 = new TabItem();
TabItem myTabItem2 = new TabItem();
TextBlock myTextBlock1 = new TextBlock() { Text = “This is on Tab 1″ };
TextBlock myTextBlock2 = new TextBlock() { Text = “This is on Tab 2″ };
myTabItem1.Content = myTextBlock1;
myTabItem2.Content = myTextBlock2;
myTabControl.Items.Add(myTabItem1);
myTabControl.Items.Add(myTabItem2);

Notice how flat the code looks when compared to the XAML. In the code, the same object that has a reference to the TabControl has a reference to each TabItem and TextBlock.

Imagine that you need to change the text on the TextBlock that is on Tab 2. With the XAML, you would need to walk the visual or logical trees to get a reference to the object. With the code, you already have a reference to all of the objects without walking any trees. You can simple write

myTextBlock2.Text = “New text for Tab 2”;

We really have three trees in WPF: the visual tree, the logical tree, and the ownership tree. With the code above, all of the controls have the same owner. If the owning object were a dialog, for example, the dialog may have references to every item on it. Therefore, it does not need to walk the visual or logical trees to get to its controls. The ownership tree is therefore flatter than the visual and logical trees.

I have seen developers spend unnecessary effort trying to make their business logic match the visual hierarchy of the controls. I would argue that this is counter-productive. Just because a dialog’s visual hierarchy has, say, ten levels does not mean that the business logic must have ten levels.

The business logic is mostly independent of the control-layout logic. It may not be entirely independent. For example, the dialog may not expose references to its controls to the outside world. Therefore, whoever owns the dialog does not own the controls on the dialog (unless they are intentionally exposed through a public API). Thus, the ownership hierarchy has a dialog at one level and all of the controls at a second level.

I thus recommend thinking in terms of three WPF trees: the visual tree, the logical tree, and the ownership tree.

Please feel free to comment with your own experiences.

Thanks,

Dale

I like to build abstraction layers over Windows to insulate my applications from the low-level details of the operating system. For example, instead of writing code like

System.Windows.Window window = new System.Windows.Window();

I would instead make my own Window class, which for this example, I’ll call ZWindow. Now the code looks like this:

ZWindow window = new ZWindow();

The ZWindow class will in turn likely create a System.Windows.Window window, which is a WPF window. However, on Silverlight, it might instead create a System.Windows.Controls.Grid since Silverlight does not have a System.Windows.Window class. Thus, the ZWindow constructor might have code like this:

#if SILVERLIGHT
System.Windows.Controls.Grid grid =
new System.Windows.Controls.Grid();
#else
System.Windows.Window window =
new System.Windows.Window();
#endif

If you write an application that uses a ZWindow class, you need not care about the difference between WPF and Silverlight.

After experimenting with various ways of organizing my abstraction layer’s projects and solutions in Visual Studio to accomplish this shared codebase between WPF and Silverlight, I have settled on the following approach:

  1. You cannot mix WPF and Silverlight within the same Visual Studio project. Thus, you need two projects that share the same source files.
  2. Do not think of one project as the primary and the other as the secondary. Treat them equally.
  3. Put your shared source files in a folder of their own—not in the same folder as any Visual Studio project files.
  4. In your two Visual Studio projects (one for WPF and one for Silverlight), link to all of the source files that need to be shared. Thus, you’ll have three folders total—one for the shared source files with no projects, one for the WPF project file with no source files, and one for the Silverlight project file with no source files. (NOTE: In Visual Studio, to link to source files without it automatically copying them to your project’s folder, select “Add Existing Item,” and then instead of clicking the Add button to dismiss the dialog, click the little down arrow on the right side of the Add button and choose Add as Link.)
  5. Create one Visual Studio solution for WPF and another for Silverlight. Do NOT try to cross compile within the same Visual Studio solution. While technically sound, I do not recommend it due to solution clutter. The projects in each solution will look the same, but will be specific to WPF or Silverlight.
  6. Create additional solutions for any applications that need to be compiled with the abstraction layer for either WPF or Silverlight. Do not combine application-specific projects with framework types of projects.

Thus, instead of this:

Folders with shared files:
Project 1 Shared Files
Project 2 Shared Files
Cluttered Solution:
Project 1 WPF
Project 1 Silverlight
Project 1 Smartphone
Project 2 WPF
Project 2 Silverlight
Project 2 Smartphone

Try this:

Folders with shared files:
Project 1 Shared Files
Project 2 Shared Files
WPF Solution:
Project 1 WPF
Project 2 WPF
Silverlight Solution:
Project 1 Silverlight
Project 2 Silverlight
Smartphone Solution:
Project 1 Smartphone
Project 2 Smartphone

In my experience, as projects get larger, the second approach scales more elegantly.

Please feel free to provide feedback for this blog entry and to share your own experiences with multi-platform development.

Thanks,

Dale

For several days, I looked for hooks into the Windows Presentation Foundation (WPF) System.Windows.Controls.TextBox control to display shadowed text:

image

WPF does not make the shadow effect easy. Changing the Foreground property can change the text color to any brush (even to a video or an image brush), but it does not achieve the shadow effect.

Using Snoop, I looked at the visual composition of a TextBox:

image

The TextBoxView control shown in Snoop does not have a public API. Lester Lobo says in this WPF forum post, “It is an internal lightweight class handling the rendering of content in the textbox.” If you re-templated a TextBox to try to replace the TextBoxView, you would have to implement all of the text-management functions provided by a TextBox—no small undertaking.

I then found a blog entry by Ken Johnson on CodeProject.com describing a clever hack for tricking a TextBox into doing what I wanted. His article is called CodeBox 2, and it uses the following algorithm:

  1. Derive a class from TextBox.
  2. Set the Foreground property to Brushes.Transparent. This hides the TextBox’s built-in text rendering.
  3. Override OnRender().
  4. Create a FormattedText object with the TextBox.Text string and set some properties to make it align and wrap just like the TextBoxView would normally do.
  5. Call DrawingContext.DrawText() to output the FormattedText such that it draws in the exact same position as the TextBoxView would normally do. To achieve the shadowed text effect, first use DrawingContext.DrawText() to draw the shadow offset a couple of units from the primary text, and then call it again to draw the primary text.
  6. What you now see is your shadowed text in a fully-functional TextBox. If you highlight text, you are actually interacting with the transparent text that is drawn in the TextBox.

image

It may be a hack, but it’s a clever hack, and aside from some scrolling and margin adjustments described well in Ken Johnson’s article and code, you can implement it relatively painlessly.

WPF’s in-depth text formatting features pay a price in CPU performance. This custom TextBox pays an even bigger price. First, drawing transparent text likely goes through all the formatting and rendering steps for no obvious visual effect. The text formatting likely provides some hit-testing and/or control sizing (layout) features even when formatting invisible text. Second, in addition to drawing transparent text, constructing a new FormattedText object and calling DrawingContext.DrawText() twice (once for the shadow and once for the primary text) adds overhead.

While I have not tested performance of my shadowed-text custom TextBox as shown in the screenshots above, I imagine that it will perform well enough on mid-level computers even with large amounts of text. However, if your application used these shadowed text effects in many places, the accumulation of CPU overhead would likely add up to significant performance problems.

I would appreciate any comments about other ways to draw shadowed text in a TextBox or to gain hooks into TextBox’s inner workings.

Good luck!

Dale

Technorati Tags: ,,

Some developers pride themselves on writing flexible classes, making as few assumptions as possible about how other objects would use them. This sounds good, but is there such a thing as excessive flexibility?

“Excessive flexibility” implies that a class fails to do enough decision-making or encapsulation on its own, so you have to do it in the calling code. In an effort to provide a flexible class, a developer unintentionally provides a class that requires more work to use and allows less room for performance optimization.

I encounter business classes similar to the one below. This class opens a text file and provides a List<string> where each item in the list represents one line of text in the file.

public class SomeDataClass: IDisposable
{
string path;
StreamReader streamReader;

public SomeDataClass()
{
}

public SomeDataClass(string path)
{
Initialize(path);
}

public void Initialize(string path)
{
this.path = path;
}

public void Open()
{
if (streamReader != null)
streamReader.Close();

streamReader = new StreamReader(path);
}

public void Close()
{
streamReader.Close();
streamReader = null;
}

public void Dispose()
{
if (streamReader != null)
{
streamReader.Close();
streamReader = null;
}
}

public List<string> GetLineData()
{
var newList = new List<string>();

while (!streamReader.EndOfStream)
{
newList.Add(streamReader.ReadLine());
}

return newList;
}
}

The public API includes a constructor, Initialize, Open, Close, Dispose, and GetLineData. This class provides some flexibility features:

  1. You can create one using a convenient parameterless constructor.
  2. You can use the constructor overload that automatically initializes the object.
  3. You can open the file only when ready to read it.
  4. You can close and then reopen the file without creating a new class instance.
  5. You can call Dispose instead of Close if you prefer.

I would have some questions for a developer who wrote that code:

  1. Will you provide documentation on best practices when using this flexible class?
  2. Why does it need the complexity of two constructors instead of one?
  3. Does the object provide a useful service when constructed by not initialized?
  4. Does the object provide a useful service when initialized, but not opened?
  5. If Close and Dispose do the same thing, why have both?
  6. Could dispose-and-new-again replace the close-and-then-reopen functionality?

I simplified this class:

public class SomeDataClassSimplified
{
string path;

public SomeDataClassSimplified(string path)
{
this.path = path;
}

public List<string> GetLineData()
{
var newList = new List<string>();

var streamReader = new StreamReader(path);

while (!streamReader.EndOfStream)
{
newList.Add(streamReader.ReadLine());
}

streamReader.Close();

return newList;
}
}

This version provides the same functionality with only two methods. Does this class require documentation? Notice that instead of creating the StreamReader in the constructor, Initialize, or Open, it creates it only as needed. This optimization results from having more implementation flexibility inside the class whereas the first version provided more flexibility outside the class.

While I contrived this over-simplified example, the same concepts apply to large business objects.

I worked with an architect who likes the term “appropriate.” In the case of business-object flexibility, I am looking for “appropriate flexibility” in the public interface, which in most cases means, “as simple as appropriate.”

I offer a few guidelines when writing business objects:

  1. Avoid overloading constructors. A constructor should require those parameters it needs in order to reach a usable state to avoid the need for Initialize types of public methods.
  2. Avoid providing developers convenience methods that add no real value. In the first example above, just as in the StreamReader class written by Microsoft, the class provides two ways to do the same thing: Close and Dispose. A developer trying to use your class will need to read documentation to figure out how to use your class.
  3. Reduce the public interface to your class in order to provide more “wiggle room” inside the class for optimization.
  4. Write self-documenting public interfaces. The first example does not make clear the difference between the constructor, Initialize, and Open. The second example self-documents.
  5. Carefully consider the number of object states you allow. The first example has at least four valid states: (1) constructed, but not initialized, (2) constructed and initialized, but not opened, (3) constructed and initialized and opened, and (4) constructed and initialized, but closed/disposed. The second example has two states: (1) constructed and (2) disposed.
  6. Avoid exposing invalid object states. In the first example, constructing an object and then calling GetLineData would fail.  Similarly, closing the object and then calling GetLineData would fail. In complex applications, the more you expose opportunities to use classes incorrectly, the more often it will happen.
  7. If you do not immediately need a business object, do not construct it. Wait until you need it to consume the memory. Generally, dispose it as soon as you no longer need it to free resources. Write code that allows business object references to remain null most of the time.

Please add comments to refine these ideas for appropriate business-object flexibility or to show your support for these ideas.

Good luck,

Dale

Technorati Tags: ,

For ideas on when to implement IDisposable, see another of my blog posts, Implement IDisposable More.

If you decide that your class should implement IDisposable, you have done your part to be sure that resources can be cleaned up immediately with a call you your Dispose method.

However, what if another object fails to call your Dispose method? Your Dispose method will never run.

In most cases, if a Dispose method does not run, I consider it a coding error. To catch it, I developed this simple enforcement trick:

public class SomeDisposableClass: IDisposable
{
bool isDisposed;
StreamReader myStreamReader;

public SomeDisposableClass()
{
myStreamReader = new StreamReader(“c:\foo.txt”);
}

public void Dispose()
{
isDisposed = true;

if (myStreamReader != null)
myStreamReader.Dispose();
}

#if DEBUG
~SomeDisposableClass()
{
if (!isDisposed)
Console.WriteLine(“An instance of SomeDisposableClass was not disposed before garbage collection.”);
}
#endif
}

A private field called isDisposed defaults to false, but is set to true if the Dispose method runs. If the Dispose method does not run, a finalizer catches the coding error by outputting a message to the console window.

Objects with finalizers pay a garbage collection performance penalty. To avoid that penalty, the above code only compiles in the finalizer in debug mode.

Typically, you can spot these error messages in the console window when garbage collection runs at application shut-down. However, they can show up at any time if your object is garbage collected sooner.

If you really want to enforce that your Dispose methods get called, throw an exception instead of outputting a message to the console window.

Be careful what you do in your finalizer. The finalizer will run on a garbage-collection thread, so avoid the temptation to reference any non-thread-safe fields. While it would be nice to pop up a message box to report not-disposed errors, during application shutdown, you may or may not catch a glimpse of it before shutdown completes.

Please add comments to refine the use of IDisposable or to show support for this enforcement trick.

Enjoy,

Dale

Technorati Tags: ,