Monday, December 22, 2008

WPF - data templating

Well, I found the weird facts about WPF (at least I think that they are weird) during resolving the first question from the list of the prior post:

How to hide the column headers for WPF list view controls?

I found no way to disable the column headers for WPF ListView control and no way to disallow the resizing of the columns. However I learned WPF feature called "data templating" which is new for me. Data templating allows you to define the appearance of the items in ListBox and ListView control. Data templating allows you to define the relation between the visual components properties and data source. To achieve my needs (show the data using multicolumn grid view but do not show the column headers) I should use ListBox control specifying the data template for the ListBox items. MSDN shows the examples of the data templates using XAML syntax only, i.e.:
   <TextBlock Text="{Binding Path=Name}" />
   <TextBlock Text="{Binding Path=Value}"/>

But creating the Data Template programmatically topic looks like somewhat classified. Well, let’s look at this topic closer. ListBox and ListView types have ItemTemplate property which is inherited from ItemsControl class which represents a control that can be used to present a collection of items. The type of ItemTemplate property is DataTemplate class. DataTemplate overview in MSDN also has only XAML syntax bases examples. DataTemplate class has VisualTree property which should be set to define the appearance of the items. Actually this is not that explicitly stated in MSDN. Then the type of VisualTree property of DataTemplate class is FrameworkElementFactory class. The description of this class says:

"This class is a deprecated way to programmatically create templates…not all of the template functionality is available when you create a template using this class. The recommended way to programmatically create a template is to load XAML from a string or a memory stream"

So, guys in MS believe that creating the data templates programmatically is a deprecated way! It sounds like terrific fact for me. However, I tried to find the limitations that exist for creating the data templates programmatically and instantaneously faced the problem. First of all I tried to create the visual tree for the data template that is shown above (stack panel has 2 child textblocks, the 1st textblock is bound to Name property of data source item, the 2nd textblock is bound to Value property). Operating on FrameWorkElement factory is weird itself. Look at the code:
private static FrameworkElementFactory CreateDataTemplate()
   var txtNode = new FrameworkElementFactory(typeof(TextBlock));
   txtNode.SetBinding(TextBlock.TextProperty, new Binding("Name"));
   var valueNode = new FrameworkElementFactory(typeof(TextBlock));
   valueNode.SetBinding(TextBlock.TextProperty, new Binding("Value"));
   var stackPanelNode = new FrameworkElementFactory(typeof (StackPanel));
   stackPanelNode.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
   return stackPanelNode;

So, to create the visual tree for the data template programmatically I need to manually replicate the corresponding XAML nodes tree in the code and this way has limitations.
Let’s return to the goal I wanted to achieve:
Show the data using multicolumn grid view but do not show the column headers.
Basically I need to show the data in ListBox control and define the data template with visual tree that is Grid control:
  <ColumnDefinition Width="100" />
  <ColumnDefinition Width="50" />
  <RowDefinition />
 <TextBlock Text="{Binding Path=Name}" Grid.Column="0" Grid.Row="0" />
 <TextBlock Text="{Binding Path=Value}" Grid.Column="1" Grid.Row="0" />

Well, I tried to create this visual tree programmatically:

private static FrameworkElementFactory CreateDataTemplate()
   var txtNode = new FrameworkElementFactory(typeof(TextBlock));
   txtNode.SetBinding(TextBlock.TextProperty, new Binding("Name"));
   txtNode.SetValue(Grid.RowProperty, 0);
   txtNode.SetValue(Grid.ColumnProperty, 0);
   var valueNode = new FrameworkElementFactory(typeof (TextBlock));
   valueNode.SetBinding(TextBlock.TextProperty, new Binding("Value"));
   valueNode.SetValue(Grid.RowProperty, 0);
   valueNode.SetValue(Grid.ColumnProperty, 1);
   var rowDefNode = new FrameworkElementFactory(typeof (RowDefinition));
   var col1DefNode = new FrameworkElementFactory(typeof (ColumnDefinition));
   var col2DefNode = new FrameworkElementFactory(typeof(ColumnDefinition));
   var rowsDefNode = new FrameworkElementFactory(typeof (RowDefinitionCollection));
   var colsDefNode = new FrameworkElementFactory(typeof (ColumnDefinitionCollection));
   var gridNode = new FrameworkElementFactory(typeof (Grid));

Executing this code throws the following exception:
"'RowDefinitionCollection' type must derive from FrameworkElement, FrameworkContentElement, or Visual3D."
Yep! You can’t create the visual tree nodes for types which are not derived from the listed types! This is the main limitation of creating data template programmatically.
When I faced that I thought that I made some mistake, I thought – well, probably I can load the data template from pre-defined XAML visual tree that is based on Grid definition and look how VisialTree property value is constructed? Nope. If you load the data template from XAML content, then VisualTree property of DataTemplate instance is null.
So, the only way to construct the data template programmatically is load it from XAML fragments. I think that this is very weird fact.
Indeed I can be asked – why do you need to create the data templates at runtime? Do you know any live use-case of that? Yes, I know.
The first idea that came to my mind when I learned the data templates is we can create the simple reporting engine using WPF capabilities. The reporting engine that seems like ActiveReports would be created very easy. End users would specify the data they want to show and the data item template exactly like ActiveReports designer. Then the engine would construct the data template programmatically and show the data in WPF ListBox control. With the current way of operating on Data Templates programmatically this is not possible.
Well, once again returning to the problem that I tried to resolve – I made it by using Grid based data template that is loaded from XAML resource file. The code is trivial.

Sunday, December 14, 2008

WPF - the power of data binding

During last 2 weeks I was distracted from VS.NET 2010 learning. We prepare the next release of Data Dynamics Reports and I am totally occupied by coding, code reviewing and testing.

However, one of the tasks I am working on turned me onto looking at WPF and I would like to write about it here.

Well, one of the common tasks in Windows Applications development is presentation of the data. You might want to show SQL Server table data in the DataGrid control or show the list of items that come from GData sources.

I worked on the code which is intended for show the collection of the business objects in such a way that the presentation is multi-column grid view where every column shows the certain business object property value. The collection of business objects may change dynamically – the end user can add the new items, delete the existing items and change the object property values. The presentation has to reflect these changes immediately. The presentation should not provide edit capabilities itself. The rest of UI provides end-users with tools that allow editing the collection.

.NET 2.0 Windows Forms include ListView control which is exactly that I needed – it shows the list of the items and every item can consist of sub-items and every sub-item can be shown in the new column.

However, .NET 2.0 ListView has the great hole – it doesn’t allow data binding. That means:

  • I need to initialize ListView items collection by going through the business object collection, creating ListViewSubItem object for every property value, then creating ListViewItem for every object, then adding the new items in ListView.
  • I need to handle the business object collection changes and re-initialize ListView items.
  • I need to handle the business object properties values changes and reflect them in ListView control.

All these stuff doesn’t seem straightforward, yep? However, .NET 2.0 can’t offer any other solution except of DataGrid control which isn’t suitable in my situation by the number of reasons.

Well, I thought – “How did they change the situation in WPF?” I have heard that WPF has the super-awesome-cool data binding capabilities. And I looked at how I can implement my task using WPF. I was impressed. ListView control in WPF supports data binding as any other control. To bind the collection of business object to list view control you just need to ensure that the collection class implements INotifyCollectionChanged interface in order to reflect the changes in the collection immediately and INotifyPropertyChanged interface in order to reflect the changes in the object properties values. .NET 3.5 provides ObservableCollection<(Of <(T>)>) Class which implements both of interfaces. The code to bind the data to ListView is pretty straightforward. Say I have the following business objects class:

To create the collection that is bound to ListView control I use the following code:

And to bind this collection to list view I use the following code:

That’s all! Looks very cool, doesn’t it?

After I tried this, the new question came to my mind. I didn't find the obvious solution for them.
  • How to hide the column headers for WPF list view controls?
  • How to highlight the list view item when the mouse is over it?
  • How to set the background for the selected item?
  • How to disable the columns resizing capability?
Well, I will try to figure it out and write about any interesting:)

Thursday, December 4, 2008

VS.NET 2010 - the illusion of the built-in TDD support.

TDD means Test Driven Development. Every person involved in the software development used it or at least heard about that. VS.NET 2010 "what's new" documentation has the "TDD support" item in the list of the new features. What would it mean? How did they make the support of software development philosophy in IDE? I tried to figure it out and was totally disappointed...
Well, there is the new Project Template in VS.NET 2010. It is called "Test Project" and it's description is "The project that contains the test":) In reality this is the Class Library Project that has the reference to the new MS assembly that contains classic "TestFixture", "Test" attributes, assertion methods and so on. Also, the newly created project contains the class with the test methods and text file with the brief description of TDD concept.
So, once you start the development keeping TDD in mind you should start with writing the new test. The test typically consists of creating the new instance of some type, invoking this type methods and compare the real results of something with the expected result. You write the code that creates the new instance of non-existing type. Visual Studio IDE reports about the error. You click on the smart tag near the code that creates the instance of the non-existing type and IDE creates the new type for you. Then you can run the tests, see if they fail, fix the code, run the tests again and so on.
So, what actually MS did for "TDD support"?
  • They created VS.NET add-in that allows to automatically create the new classes, methods, properties, indexers and so on by clicking on the smart tags near the piece of the code. Frankly, it can be done for a couple of days by every programmer who intimate with VS add-in development.
  • They created the new assembly that actually copies NUnut.Framework assembly. Yeah, I bet no one will want to re-write tons of unit tests created using NUnit or MBUnit using this new library.
  • They added the tools that allow to run the unit tests that created using the MS unit tests library.(Resharper has the tools that allow to run NUnit tests from IDE:))
  • They added the new Project Template which is actually not new.
  • They called all these stuff "built-in TDD support".
And I am ready to hear the words like "TDD makes your business flow easier and VS.NET 2010 has the TDD support!" in MS sessions.
So, what is conclusion? The conclusion is - MS developed the pretty simple and useless feature, packed it to the nice wrappers and called it "TDD support!"
Everyone knows what would be result if pack the useless feature to the nice wrappers.

Sunday, November 30, 2008

VS.NET 2010 - Call Hierarchy

Every day I use the splendid VS.NET add-in called ReSharper in the development routine. This tool greatly reduces the amount of efforts that are needed to find the syntax errors in the code, refactor the code, search various entities of the code, etc. etc. I don't realize how I can code without using ReSharper.
One of the pretty useful features of R# is "Find usages..." functionality. Right click on the method, property, constructor, type, etc., then select "Find Usages" or "Find Usages Advanced..." and R# shows you the points of code where the selected entity is used. You can find the derived classes of some base type or the implementations of some interface, etc. etc. This is really great feature and it has a lot of options...Now I realize that this feature and R# doesn't provide another brilliant option...
So, sometimes I need to analyze
the convoluted and very complex code to figure out how it works to find the possible flaws or realize the possible solution for the newly required features. Say I am interested in some method("A" method), I want to figure out it's place in the the flow of code execution. If I don't want to debug the code I usually use Find Usages feature if R#. I find the usages of the method A. Let's say method A is called by methods B and C. This fact isn't very informative. Then I need to find the usages of the methods B and C, etc. etc. Then I need to realize the entire picture of the place of method A in the flow of the code execution based on the list of usages of the related methods and believe me, this is not pretty straightforward in the complex code(or I am just retard:))
Anyway, VS.NET 2010 introduced the new feature called Call Hierarchy and this is exactly what I needed for more productive and quick code analysis in the complex projects! Right-click on the method, property, constructor or indexer then select "View call hierarchy" and Visual Studio shows you the entire picture of the selected entity place in the flow of the code execution. It shows the calls to "method A" that I referred to in the previous paragraph and calls from "method A". For every calling or called method VS shows it's invokers and invoked methods. You can navigate to calling or called methods and change the scope of call hierarchy analysis! Here is the screen shot of the call hierarchy of the piece of the code of one of my projects:

I am impressed by this new feature and undoubtedly I will use it every day once the standalone version of VS.NET 2010(outside of virtual machine) is released :)

Thursday, November 27, 2008

VS.NET 2010 - the first look

As I supposed the guest operation system in virtual machine that hosts VS.NET 2010 is Windows Server 2008! It has VS.NET 2008, VS.NET 2010, SQL Server 2008, Office 2008, etc. installed.
It's now clear why you need 75 GB on hard drive to get this heavy virtual PC image :)
The first thing I looked for is documentation for VS.NET 2010. It would allow me looking at new features in VS IDE, C#, etc..and..there is no MSDN available! The only available documentation is the set of walkthroughs that briefly describe the new features. Okay, I briefly read this document..
The first feature that I liked and tried immediately is customizing the VS.NET 2010 Start Page. Start page for now can be any content that is built using WPF. It has no limits - you can add RSS feed, animation, flow documents, etc. in the Start Page. You can bind the VS commands to the elements of start page, i.e. execute any main menu item commands.
The steps that needed for customization are pretty straightforward - create XAML document that contains the start page content, copy it to the certain folder and voila!
Well, I tried that and now my Start Page looks like below

That's all for this brief post:)

Wednesday, November 26, 2008

Visual Studio .NET 2010 installation.

Some time ago Microsoft announced Visual Studio .NET 2010 and shared the pre-release CTP for everyone. Splendid! Awesome! - it was my reaction to these news.Then I found CTP download page and looked at the requirements..What?? 75GB available on hard-drive? Core Duo 2 GHz processor?? Must have a minimum of 2 GB RAM?? Indeed these requirements aren't for VS.NET 2010 itself. They are actually for running virtual machine on which VS.NET 2010 is hosted. I suppose that the guest OS on this virtual machine is Windows Server 2008 at least:)
Well, my machine had :

But I was so excited about VS.NET 2010 as I decided to upgrade my machine so that it satisfies running virtual machine that hosts VS.NET 2010 requirements :)
I never thought that some programming software would lead me to upgrade the hardware..Well, the weird Microsoft way to release CTP's actually led me to that.
Now my machine has:
And I can install VS.NET 2010 for now and learn the new interesting features like dynamic features of C# or parallelism support.
I will keep writing about these things!