Beyond Hello World - My First WPF Application (with source)
My pet project for the holiday vacation has been writing a WPF application to view data from my code line counting tool CLC.EXE (soon to be released on Codeplex). CLC produces counts of lines, code, comments, and other statistics per file, per directory and for entire directory trees. When complete, the CLC data viewer (CLCV) will read a CLC data file and display various visualizations of the data such as a tree map (see also, and also), some pie charts and perhaps a histogram or two.
I’ve included the first working CLCV application shell in the attached zip file. This project builds in Visual Studio 2005 (any version). I used Microsoft Expression Blend to design the UI. The app-shell currently implements the application’s initial UI panel which gives the user the opportunity to open a new file, or select a recently opened file. This panel has the following features:
- It keeps track of the most recently opened files, keeping the sorted with the most recently opened file at the top. It also manages the list
- When CLCV starts, it deletes any files from the list that no longer exist
- When the user clicks on a file name that no longer exists, the name is removed from the list and the user is notified with a simple message box.
- It uses XML serialization to save the recently opened file list.
- It saves the recent file list in the users application data directory (not under My Documents)
- When running on Windows Vista, it uses the new file open dialog box.
I still have few things to do for CLCV’s initial UI panel:
- The main UI needs a close button, but I haven’t yet figured out how to close a WPF window.
- The main UI panel needs to remember its position – currently it always appears in the center of the screen.
- For native applications, I usually create a console window for simple debug spew, but this doesn’t seem like the “.Net Way”. I need to figure out how to effectively use the Debug and Trace classes. For example, how do I get the debug and trace output when I’m not running the tool under the VS debugger?
This is my very first foray with both WPF and C#. My only material exposure to managed code has been some utilities written in managed C++ so I could use the excellent Dundas Charting products. I used managed C++ because I was in a hurry and needed to leverage my existing class libraries (this worked well).
So I was pleasantly surprised that getting the UI shell and initial UI panel up and running was astonishingly easy to do; especially given that I could barely spell WPF and C# a week ago. The most amazing thing to me is how little code was needed is to do all this; 161 lines of C# code and about 80 lines or so of XAML. This is probably at least an order of magnitude less code than it would take to do all this in native C++, even with a nice class library like WTL and ATL. Not only is it less code, it was also easy to do – the compile-test turnaround time is super fast and the VS environment and debugger has deep knowledge about the C# language and .NET class libraries. Intelisense is really helpful and saved me loads of timing having to go back and look at documentation. VS’s C# editor is also quite good at finding syntax errors without compiling, saving more time.
I'm sure that someone will point out that even doing this right on top of Win32 in C could be done in a small amount of code. I'm confident that is true in a limited way - but doing this with Win32, or even WTL/ATL would be a lot more code to get the same app behavior and features that are inherent in a C# and WPF application: the blended background, the nice use of fonts and colors, transparent controls, the nice use of animation to highlight focus, the flow and layout capabilities that let windows be resized and maintain a useable and attractive layout.
It took me about 15 minutes to develop a nice look and feel for the initial UI panel in Blend. There is simply no comparison here for native UI code - its all done by hand! The ability for UI designers to work efficiently with developers is a revolutionary capability.
There are other things I like about WPF and .NET as well:
- The WPF controls, their properties, methods, and events, seem much consistent and coherent than those from Windows.Forms.
- Microsoft Expression Blend is really easy to use and looks like it will be a great tool even at V1.0.
- If you use Blend to start Visual Studio, they work nicely together.
- I like Intelisense with native and managed C++, but wow, it sure is awesome with C# - the editor and dev environment know WAY more about C# than they do C++.
- I really like how well the XAML code and the C# partial classes fit together: The C# code can simply reference objects defined in XAML by their name which is defined by the “x:key” attribute.
I did run into a few issues though:
Blend is a memory HOG. My system has 1GB of memory and running dev studio and blend together often cause a lot of paging.
- The idea behind XAML is great, but I think the implementation in XML is clunky. It seems that every new thing at Microsoft uses XML. Is that always the right choice? Does a having a good hammer make every problem a nail?
- Data binding is still confusing to me…. It sure seems complicated, but I suspect that I just need to work on groking it…
- There is a TON of documentation on WPF, .NET 3.0 etc, but I still find it difficult to figure out how to do simple things.
- For example, I needed a simple way to save and restore the recently used file list. The .NET Configuration class seemed like a good place to start. I spent about two hours dorking around with the Configuration” class before I gave up. It and its related classes are way too complicated and the examples were SuperCrapy™. So, I tried XML serialization. It took me about 15 minutes to get the save and restore functionality working – nice… J
- There seems to be a lot of name space overlap between .NET 3.0 (WPF) and Windows.Forms. Of course, this is why we have namespaces! But, the MSDN docs don’t really make it clear at the top level what is what – everything is under the class library hierarchy.
- Glork! Why in the heck do the .NET classes not support the new vista dialog boxes??? While Sven Groot’s classes are really handy (and nicely implemented), I shouldn’t have had to use them. Am I missing something? Is Sven missing something? Perhaps so…
It is important to note that the benefits of WPF, C#, and managed code in general come with costs. These applications are by their very nature larger in terms of memory and CPU utilization. Our experience on the client performance team is that it takes a lot of work to ensure that a managed application launches quickly, remains responsive to user interactions, performs well in terms of throughput, scales well to large data sets, and is a "good citizen" in terms if system resource utilization.
Good performance for managed applications is certainly possible, but developers need to be aware of the costs associated with managed applications, design for performance up front, and use performance tools (such as logging and profiling) to maintain good performance during the development process.