Today's issue


I’ve needed a good way to display code that has some nice formatting. I’m trying out ‘Insert Code for Windows Live Writer’.

namespace Commons.Test {
    public class TestPresenter {
        private ITestView view;
        private ITestService service;

        public TestPresenter(ITestView view) : this(view, new TestService()) {}

        public TestPresenter(ITestView view, ITestService service) {
            this.view = view;
            this.service = service;
        }
    }
}

This is a test of the code inserter. This is much better than no code formatting at all but I would like to find the code box with the scroll bars I see in other blogs. I’m going to keep looking.

I was working on extending the DataControlField to display an icon based on an integer out of the database. There were four possible icons to display. In addition there was a requirement to show tool tip or not when hovering over the icon. This is controlled by values from the database. Here is the class code:

public class IconField : DataControlField {
private const string ONLINE_URL = “~/Images/online.gif”;
private const string OFFLINE_URL = “~/Images/offline.gif”;
private const string NOT_CHECKED_IN_URL = “~/Images/chk.gif”;
private const string CURRENT_LOGIN_URL = “~/Images/login.gif”;
private const string ONLINE = “Online”;
private const string OFFLINE = “Offline”;
private const string NOT_CHECKED_IN = “Not checked in”;
protected override DataControlField CreateField() {
return new IconField();
}

public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
{
base.InitializeCell(cell, cellType, rowState, rowIndex);
if(cellType == DataControlCellType.DataCell) {
cell.DataBinding += new EventHandler(OnBindingField);
}
}

private void OnBindingField(object sender, EventArgs e) {
Control target = (Control)sender;
if(target is TableCell) {
object dataItem = DataBinder.GetDataItem(target.NamingContainer);
target.Controls.Add(createLiteralSpace(2));
target.Controls.Add(createIconDisplay((int)DataBinder.GetPropertyValue(dataItem, “Online”), (bool)DataBinder.GetPropertyValue(dataItem, “ShowToolTip”), (string)DataBinder.GetPropertyValue(dataItem, “CurrentLogin”)));
target.Controls.Add(createLiteralSpace(4));
}
}

private static Literal createLiteralSpace(int loops) {
Literal literal = new Literal();
for (int i = 0; i < loops; i++) {
literal.Text += “ ”;
}
return literal;
}

private static Image createIconDisplay(int online, bool showToolTip, string currentLogin) {
Image image = new Image();
image.ImageUrl = NOT_CHECKED_IN_URL;
switch (online) {
case 0:
image.ImageUrl = OFFLINE_URL;
break;
case 1:
if (currentLogin.Length > 0) {
image.ImageUrl = CURRENT_LOGIN_URL;
} else {
image.ImageUrl = ONLINE_URL;
}
break;
}
if (showToolTip) {
image.ToolTip = buildToolTip(online);
}
return image;
}

private static string buildToolTip(int online, string contactNotes) {
String toolTip = “”;
switch (online) {
case 0:
toolTip = OFFLINE;
break;
case 1:
toolTip = ONLINE;
break;
default:
toolTip = NOT_CHECKED_IN;
break;
}
return toolTip;
}
}

I override the InitializeCell method so I can wire up a new OnBindingField EventHandler. This will take the data from each row during the binding phase. To do this you use the DataBinder class. You grab the dataItem (the row from the GridView.DataSource) and use the DataBinder.GetPropertyValue. The second argument is the name of the property you want to get. These are class properties of the DataSource. Any GridView DataSource can be used: DataTable, IList, IEnumerable, etc.

To use this in any grid you first have to put this on the page:

<%@ Register TagPrefix=”MyTag” Assembly=”MyAssembly” Namespace=”MyNamespace” %>

Then in the grid <Columns> you refer to it with this:

<MyTag:IconField />

Easy enough, enjoy.

I posted about the task I had at work to combined an icon, a checkbox and a literal to create our own field that can be used in grid. I have made some good progress figuring this out.

The DataControlField Class is an abstract class that only requires one method, CreateField, to be implemented but many other methods can be overwritten. I’m using an IList<T> that is created via NHibernate to query three tables. The IList<T> is a class that has data and I use composition to create a contained class that itself has a contained class. This may seem a little complicated but after a few hours of experimenting I was able to figure out how to make all of this work.

The last piece of this puzzle has to do with wiring up an event handler to respond to the check changing of the checkbox. I didn’t get it done today but I hope to figure it out tomorrow.

When I get all of the pieces done I will write a more detailed explanation of how this is done. The explanation will be generic and I won’t be able to give you the exact code of course. I will be able to explain some of the trouble points and how I figured it out.

I also was able to figure out how to create custom header controls by extending the TemplateField class. The TemplateField class extends the DataControlField class so it was as easy as changing the : DataControlField of the class to : TemplateField. I needed the HeaderTemplate property of the TemplateField to make a custom header control. I could have create my own HeaderTemplate property for the DataControlField but I always let someone do the coding for me whenever I can.

So a task I have at work is to be able to manage a few different objects in a DataControlField. The objects I need to manage are: an icon, ToolTip, text and a checkbox. These objects are displayed based on a domain class and will be a fundamental building block for most of the information that will displayed in a grid.

There are three approaches to this that I can think of off the top of my head:

  • extend the BoundColumn class
  • use a TemplateField column and build it
  • extend the DataControlField class

I’m going to look at going the DataControlField class route.

I have been working off and on since Friday trying to figure out why my custom resource provider factory wasn’t working. Here is what I found out for all my efforts. This is how I can reproduce the issue.

  • In the web page design mode select the ‘Generate Local Resources’
  • Copy the App_LocalResources/<page>.aspx.resx file and rename it to <page>.aspx.es-mx.resx and translate the English strings to Spanish-Mexican strings.
  • Go to the Temporary ASP.NET Files/MyWebSite directory and delete the auto-generated files found there.
  • Run in debug mode in VS2005 and make sure that the browser Languages has Spanish-Mexico [es-mx] as the top one.

This works fine and the strings are now in Spanish-Mexican. Now do this:

  • Go to the web.config file and place this <globalization resourceProviderFactoryType=”<namespace>.<class>, <assembly>” /> in the system.web section.
  • Run in debug mode in VS2005 and now the strings come from the database.

This works fine too. Now do this:

  • Go to the Temporary ASP.NET Files/MyWebSite and delete the files in the directory.
  • Run in debug mode in VS2005.

This doesn’t work. If you look at the auto-generated files you notice that in the parsing tree controls there is a @__ctrl.Text = “English string” but there should be a second one that looks similar to this:

@__ctrl.Text = System.Convert.ToString(this.GetLocalResourceObject(“resourckey”), CultureInfo.CurrentCulture)

This isn’t there and that is why it doesn’t work. For some reason having the <globalization… /> in the web.config file doesn’t auto-generate the second @__ctrl.Text assignment. If it isn’t there then it does.

Last Friday I was working on the Internationalization of our product and had implemented a database resource provider. In .NET 2.0 you get ‘free’ localization with VS2005 > Tools > Generate Local Resource if you’re on a Web Page in Design Mode. What this does is create a .resx file in the App_LocalResources directory and places meta:resourcekey tags in all of the web controls that are localizable. It does a little more but this is the jist of it.

I then added the globalization tag to the web.config system.web section with the resourceProviderFactoryType set to the database resource provider I created.

So I wanted to refactor and add comments to the database resource provider classes that I coded. So I started to do this by having ReSharper format my code. I checked the ‘optimize “using” directives’ and hit the reformat button. I then went into the code and started adding comments before I really began the refactoring.

I went to show one of the team members how this worked and it didn’t. So I spent the rest of the day on Friday, many hours this weekend googling and the first couple of hours this morning trying to figure out what went wrong.

To make a long story short it turns out in the code behind the web pages ReSharper had removed the ‘using System.Globalization’ declaration because nowhere in the code was there an explicit call to any method in the System.Globalization package. When I added it back ReSharper still marks it as being able to be safely removed but now I know that it is needed for the generated ‘hidden’ code and the globalization that .NET 2.0 provides for ‘free’ won’t work without it.

So make sure on any web page that has globalization that it also has the ‘using System.Globalization’ if you want it to work.

I’ve been working on a DbResouceManger class that is based on the example from “.NET Internationalization The Developer’s Guide to Building Global Windows and Web Applications”.

.NET Internationalization

I did some modification to the example code and got it compiled but not working. It crashed when I first tried it but that was because I didn’t have the <globalization resourceProviderFactoryType… configuration correct. Once I got the configuration right it ran but no strings from the database.

This morning I got it working and started to add only comments to the code so I will remember what is what when I go to refactor the whole DbResourceManager and it’s supporting classes and interfaces.

Now I can’t get it working again. This is the only thing I hate about coding. I’m sure I goofed it up and it will turn out to be something stupid (doesn’t it always?).

As part of the scramble to get the subversion repository functional I wasn’t able to make any new directories in the repository. I could read it so I knew it was something wrong in the authorization file. Here is what I had:

[groups]

svn-admins = a, b, c

ccnet-ci = ccnet

the-committers = x, y, z

[/]

* = r

# give committers read-write access

the-committers = rw

@ccnet-ci = r

[/tags]

@svn-admins = rw

@ccnet-ci = r

[/branches]

@svn-admins = rw

@ccnet-ci = r

It turns out I forgot the @ on the-committers so the rw wasn’t authorized. I looked at that a couple of times before I figured it out.

The other founder went over to the garage NOC and rebooted the machine. Still working on the Subversion machine. The tape backup is working. Now a full backup and restore will have to be performed. I’ll do an entry on how backup and restore Subversion repositories to tape using CommVault’s Galaxy Express.

Sometime Monday night the SourceOffSite server went down. This normally is just a reboot and everything is cool. Not this time. The server is in the garage of one of the founders and he is on vacation until Saturday. This is a problem for the fixing of bugs (we call them hotfixes) for our team and the team down south.

One of my longtime co-workers and myself have been setting up the new source control system using Subversion. A big move for the company and something we need to desperately do. The last real hurtle to jump is the tape backup. We’ve got the backing up of the Subversion repositories working but the final task is to do a tape backup and restore to finally go live. So today the pressure is on to get this last step done.

Two weeks ago I added four of the southern developers to the Subversion authentication and authorization files based on their chosen login names and passwords. I created the repository for them but nothing else. Today the rush was on to get this up and going. Finally we will be moving to Subversion. It will be good to have the functionality of Subversion compared to what we are currently using.