Why Is Everything So Darn Declarative?

WEBINAR:On-Demand

Introduction

It has been a great ride! Very few times in history have been more revolutionary than this era in which you live. Lots of great things occur at an astonishing speed (sometimes bad things). With the Internet, ideas flow more freely than ever before. As always, humans are learning how to exploit this new medium.

In the programming industry, there has always been this tendency to look for the holy grail of codeless software development. There are many ideas of having some sort of subject matter expert code (wizards) writing your tedious code for you. The danger you face as programmers is the tendency to grow dependent on these tools to the point where you lose your ability to code or perform certain tasks yourself. I personally don't have any problem with automation as long as it truly solves a problem for me without leaving me impotent. Often, you are given tools that are very glossy and cool but do not cover every possible situation. No tool can, really. So, when the tool fails, you are royally screwed. To me, that's a real problem.

Today, technology is coming at you at an astonishing rate! It is coming at a much faster rate than is humanly possible to assimilate. Already, getting your hand around something like the .NET Framework is nearly impossible for one individual to have full mastery of it. Microsoft tries really hard to make things easier for you by giving you things like IntelliSense, code completion, snippets, and wizards to help you be more productive. I believe that is a good thing. However, you should not forget your roots. You are programmers and, to some extent, more than that. You have a responsibility to yourself and your industry to maintain some level of competency. I believe you are moving too fast without any introspection, too quickly with little or no analysis of the situation. You become overly dependent on your tools to do the job. I hate to use a cliché but I would rather be taught how to grow my own food than be given a plate of food. Those of you who like science fiction and movies may remember the following line from a famous movie.

"Don't you see the danger in what you are trying to do here? You took what others had done and before you knew what you had, you packaged it and..."

I am, of course, paraphrasing from of a line in Jurassic Park. However, I believe it is very applicable to the point I am trying to make. My warning is for you to be aware that every time you take a shortcut in order to meet a deadline, it may come at a subtle but serious price. Be aware of the tradeoffs in question. I realize we all have to make compromises to get things done. But, be aware of the cost of such shortcuts to you as a developer. Okay, by this time you must be asking. What exactly is your point? I tell you by sharing a real life experience.

I am going to take a very small slice of a simple application I am currently working on. This application is not glamorous or sexy. I needed to have a dynamic page that could deal with multiple tables and somewhat dynamic column definitions. It would not have been practical to create a static page to handle each of the possible conditions. It had to be dynamic enough so that a rules change would not require a new maintenance page.

I set out to prototype my requirements a little at a time. I normally break down my problem into smaller problems, then try them out with code whose only purpose is testing the feasibility of my plan. The problem was to create a Master/Details page of a very dynamic nature. The traditional examples provided by Microsoft always involved the use of data source controls such as SqlDatasource and ObjDataSource. These guys and a dose of wizards and you had a static page that would do part of the job. And, the great thing was it was done in minutes! Only one problem, it was static. I could not see how I could turn this declarative crap into a dynamic page capable of handling multiple queries dynamically by one GridView and DetailsView control. I needed some code to do this.

I broke down my code even further and started with just a GridView on my page. I knew this control has a property called DataSource. I knew what it did based on my experience with DataGrid. Back in those days, you did a lot stuff programmatically. All I had to do was provide a reference to a DataSet or DataTable then invoke Databind method and I was done.

I ran into a number of issues with the DetailsView, however. I decided to Google the problem. I spent a considerable amount of time on this and didn't find much. Then, I went to one of the Microsoft forums and asked the question. The response was surprising; some guy named Phil started to berate me about my improper use of the Detailsview and told me that what I wanted to do could not be done because was not designed to be used in that manner.

I don't know about you guys, but I felt those were fighting words. I proceeded to flame the guy to no end. A day later, I posted part of the answer on how to perform column definition and bind all programmatically, without the use of a datasource. This is what I intent to share with you guys in the hope that something of some value comes out of this. Maybe some of you have even a better approach. This I would love to hear, or just your opinion.

So, my prototype looked something like what you see below. I had a drop-down to simulate my dynamic table or queries and the idea was that this page would adapt to the query dynamically and render the information.

The finished product looked as shown above and it was all done programmatically.

The first line is hitting an object that brings back a datatable. You would, of course, replace that with your own data access. The second line applies to the datasource property and, as usual, you call it databind. You probably seen several different incarnations of this, but that is basically it. Remember, in my exercise I am staying way from the declarative model. Everything had to be coded.

Obviously, now you need to see how to bind data to the DetailsView control.

This is pretty much the same as the GridView. As far as the ViewState material goes, it is just how I associated the selected row of the grid with what I wanted displayed on the DetailsView. I will get to that in a moment. Basically, that is all you need to populate the controls manually.

I wanted to do everything manually, that meant Fields and all. To define the columns for the grid, the following was needed:

This first group represents the select button for the GridView control.

At this point, you have what you could easily have gotten if I left auto generate fields on (see the following figure).

[Fig2.png]

Expanding the command field and selecting the select command would do the same, except now everything would be declarative, not code. In the old days, this wizard would generate code that, in my opinion, was infinitely more instructive than the declarative code generated now.

Columns are derived in the same manner as the GridView, with a few minor differences. In the grid, you use the columns collection and in the detailsview, you use the fields collection. The last code group defines the command field that allows you to link the grid and detailsview controls.

The following figure shows what the final product looks like.

[Fig4.png]

Why Is Everything So Darn Declarative?

WEBINAR:On-Demand

That takes care of the data binding. A little more logic is needed for everything to work together. The meager examples I saw on the Internet relied heavily on declarative stuff something I did not want, given the dynamic nature of my page. I relied more on controls' events to glue everything together.

To link the grid to the view, I used the grid's RowCommand event as shown below. Note that I take advantage of view state to persist the key value:

Because you're manually doing databinding, the DetailsView viewstate has to be turned off. I could have spent more time fixing this little bug, but instead I render the control every time I post back. This is something you probably should not do on production code.

To perform updates, you need to fake out the normal process. This particular event is normally used for validation and one last chance to fix or abort the update process. You can use it to manually update the database bypassing the integral update command that comes with the DetailsView.

Critical to extracting data from the DetailsView requires that long line that is cast into the appropriate control.

CType(DetailsView1.Rows(1).Cells(1).Controls(0), TextBox)

The BoundField default type contains labels for read only (displaying) and textboxes for inserting and updating. I copy the original table and populate it with the fields from the DetailsView. The business method required the new change as well as old data to perform concurrency checks. There probably are more ways of doing this than I can imagine. I am just showing one of many possible implementations. Finally, get the DetailsView control out of edit mode, refresh, and you're done.

You can look at the code for Insert and Delete on your own. The rest of my code just manages the dynamics of changing query. In this example, I only show the Customers and Products tables, but you could create some basic boiler plating for field definitions as shown and you're done.

Basically, that's it. I know that I have not covered everything in detail but I did not want to waste your time with the obvious. You can check that out on your own. Of course, I will make the source for this simple exercise available to those you who are interested.

I can understand why Microsoft pushes the declarative mode exclusively. One of the transitions from 1.1 to 2.0 was the new model for deployment driven by their belief that they could make the page more responsive. This dynamic model came at a price where partial classes were needed to hide the fact that the designer generated portion of code behind is now dynamic and no longer there which is why, I suspect, the declarative model is (at least in part) required. So, you can't cheat by peeking into the Designer-generated code to see how things are done. Now, you have to rely on reflection tools to reverse engineer all the stuff they are hiding. Microsoft does not want to stop and explain all this and instead pushes its declarative crap to the exclusion of all else. It is not necessary for them to coerce you into this way of doing things as the only solution. It should be your choice, not theirs. Since mid 2003, I've seen a shift from the open mind set back to a more heavy handed approach cloaked in a pretext—"see how easy we have made it for you!" Thanks, but no thanks!! DO NOT LIMIT MY CHOICES!!

Things Left to Do

How do you handle special situations like dropdown an maskedit controls? Once again, notice how weak the DetailsView control is from a UI perspective. The things I just motioned are non-trivial to do with the DetailsView even in declarative mode. It gets really interesting when you try to implement a template field programmatically.

In Part 2, I will show you how I came up with a solution for these issues.

Advertiser Disclosure:
Some of the products that appear on this site are from companies from which QuinStreet receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. QuinStreet does not include all companies or all types of products available in the marketplace.

Thanks for your registration, follow us on our social networks to keep up-to-date