Saturday, November 29

Refresh CellTemplate in ListView When Content Changes

There is one thing (at least) in WPF which lack update mechanism and that is DataTemplateSelector.
Imagine you implement a property grid inside a ListView control. You will have three columns: Name, Type, Value.
Name is easy, it is just a TextBox, Type is also easy, is it a combo box from which you select predefine types (string, integer, date, color).
The hard one is Value since its template has to be changed when the Type is change.

The Problem: DataTemplateSelector does not have a way of signaling that the template needs to be re-evaluated. Once WPF select a template it will stay with it.

The Solution: The solution for re-evaluating data template selector for ListView is to refresh the DataTemplateSelector bound to the column's CellTemplateSelector property.

The Explanation: I'm a fan of M-V-VM paradigm, so I usually have my UserControl or Window's DataContext property set to an instance of my ViewModel class.
In my XAML, I bind my GridColumn's CellTemplateSelector property to my TemplateSelector property of my ViewModel.

Code:

internal class EditActionPropertiesViewModel
{
private DataTemplateSelector m_ValueDataTemplateSelector = null;

public DataTemplateSelector ValueDataTemplateSelector
{
get { return m_ValueDataTemplateSelector; }
private set
{
m_ValueDataTemplateSelector = value;
OnPropertyChanged("ValueDataTemplateSelector");
}
}

internal void RefreshValueTemplateSelector()
{
ValueDataTemplateSelector = new ValueEditorCellTemplateSelector();
}
}

XAML:



<UserControl>
<ListView>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Type" CellTemplate="{StaticResource TypeCellTemplate}">
<GridViewColumn Header="Value" CellTemplateSelector="{Binding ValueDataTemplateSelector}">
    </GridView.Columns>
   </GridView>
  </ListView.View>
 </ListView>
</UserControl>
Remember that the DataContext of the grid column is the ViewModel, not each ListViewItem's DataItem.
So, any time any of the properties' Type changes, we need to signal that the TemplateSelector property has change and WPF will re-evaluate the data templates.

Saturday, November 8

Long Running Conversation with NHibernate

I am implementing a Windows Application which use WPF for presentation layer and NHibernate for O/R mapping. Off course I'm diving the application for MVC or more accurately Model/View/ViewModel due to the use of WPF.
I have been reding the book "NHibernate In Action" to try and learn how to use NHibernate in a good practice sort of way.
I have fail to find good documentation which explain how to use NHibernate in Windows Application, and more specifically how to create a separation  to layers including NHibernate (how NHibernate incorporate to MVC design pattern).

So, I've ask that question in the forum of the book and got an answer.
You are welcome to read the thread and I'll keep on update here as I'll implement the solution.

Friday, October 3

Everything is a network

The new project I'm currently working on, called Dynamic Network Adapter (or DnA for short) evolve around the idea that networks are great tool and can help model the world.

You can see it in many different areas. Social Network really took of in the past two years and this is just one area.
Computer network are part of our life.
Even terrorist networks are kind of network.

What I'm trying to say is that working with a man that thought me to see network is everything seem wired at the time. But now it much easy to watch on human behavior and process happening around us as network.

We are developing a computer model to use this network thinking for different purposes.

More will come.

Monday, August 25

NHibernate

I've start to work on a new project.
One of the base building blocks of that project is something we call "bank".
Bank can be anything from simple list of items (which maps to simple table in a database) to a complex network of objects like tree for example (which maps to several tables with relation in a database).

I've start to write some sample code to see how I can solve this problem. I've worked for a week just to produce a solution to loading a bank from a database tables. I've not yet got to saving the bank back to the database.

Then, after talking to a friend about this problem, I've got to learn about NHibernate.
After few hours of reading the getting reference document and searching the web I've got a solution for both loading and saving virtually any form of bank to and from a database tables.

I have to say I am amaze from the easy of use and the abilities NHibernate has. All the plumbing of tracking the objects state (loaded, modified, delete) are now in the hand of NHibernate, yet I can "plug" into the process using various plug-in points left by the developers of NHibernate to observe or participate in the process of loading and saving the objects.

Next time I'll write about "dynamic bank" - how to let the user define bank without the need to create database table.

Sunday, August 17

CLR Weak Event

Since .NET 1.0 Microsoft provide a standard way to register for events of objects.
One of the biggest problem of using the standard event pattern is that the lifetime of the subscriber become governed by the lifetime of the source.
There are several articles about how to overcome this problem, also Microsoft has add a new class to .NET 3.0 called WeakEvent.
I have found WeakEvent class not feat to my needs since it inherit from DependencyObject which is WPF specific object and thus not suited for usage in general program - not related to WPF.
Also, after reading some articles on the net about this issue, I have realized that most of the solution came from the source side, that is changing the object exposing the event to allow weak events, but this is not always the case - sometime you need to you compiled, closed, even seal object and to register to its events weakly.

So, the solution was involved around WeakReference class.
The idea is simple, we want to register to event of source (call it S) with the receiver (call it R).
In classic .NET event S always keep strong reference to R, usually R also keep strong reference to S.
We need to break the strong reference between S and R so that even when S is still alive, it will not keep R alive any longer then it really needs.
We do this by creating new class (call it M) which will mediate the event from the source to the receiver. M will be register to the event on S and will keep a weak reference to R. M will also need to check if R is still alive before dispatching the event.

The code:

class S
{
public event EventHandler SomeHappen;
}

class R
{
R(S s)
{
new M(this, s);
}

private void HandleSomeHappen(object sender, EventArgs e)
{
...
}

private class M
{
private WeakReference _r;
private S _s;

M(R r, S s)
{
_s = s;
_r = new WeakReference(r);
s.SomeHappen += DispatchSomeHappen;
}

private void DispatchSomeHappen(object sender, EventArgs e)
{
R r = (R)_r.Target;
if (r == null) {
_s.SomeHappen -= DispatchSomeHappen;
} else {
r.HandleSomeHappen(sender, e);
}
}
}
}

As you can see this solution is not generic.
I used a private class to dispatch the events sine I want to be able to leave the handle method in the receiver class private or protected.
Most of the work is done in DispatchXXX method which first check if the target has been garbage collected already, in this case we unregister from the event and leave M to be collected next. Otherwise we dispatch the event to the receiver object and let it handle the event.

I'm trying to make this solution more generic, but I yet to find the way.

Saturday, December 9

Synchronizing the ListViews

As you remember, I am developing a .NET project which display gantt graphs.
As we start to develope the UI part we decide we need our view to be devided into two parts: text and graph. This is the same as Microsoft Project view.

Since we need both views to display header on the top and row for each activity in the gantt we decide to use WPF ListView control. ListView inhreit from ListBox and add switchable View property as well as other features.

I will not go into details about the implementation of the ListViews here, what I would like to concentrate now is how can we synchronize the vertical scroll-bar of the two lists.

We decide that the verical scroll bar of the text view should be hidden while the vertical scroll bar of the graph view should be visible. This way we need to scroll the text view list when-ever the graph view is scroll.

After much experements and trail-and-error tests I come up with the following solution: I will walk the visual tree of the two ListViews, grab and save the reference to both ListView's ScrollViewer internal element and use it to synchronize the ListViews.

I have also consulte Microsoft WPF Development Team members and they confirm my solution is the best they can think of as of this moment.

I have written a class called ItemsControlVerticalSynchornizer which synchronize the vertical scrollbar of ItemsControl, or any dervied class. I will upload the class to this post as soon as possible.

Hope you enjoy,
Ido.

Saturday, October 28

Book Report: Application = Code + Markup by Charles Petzold

Another great book by Charles Petzold - Application = Code + Markup.

I have pre-order this book from Amazon about a month ago. I decide it better to learn from the experience of someone like Petzold and not try to learn all about WPF from the Internet.

The book is great, every paragraph teach you something new. He progress slowly but surely and address all the question you might have about almost every aspect of WPF.

Before reading that book I know WPF is awesome from the videos and screen-shoots I saw. After reading the book I am amazed from the work Microsoft had put into Windows Presentation Foundation.

This book can get you up-and-running with WPF in two weeks. That what it took me. Two weeks or reading and playing with WPF and I am now feel like I'm ready to develope great looking applications.

I really recommend this book to anyone how like to learn WPF in the right way.

Thank you Charles Petzold,
Ido.