Dynamic Data – Customizing the Delete Confirmation Dialog

I spent some time customizing the delete confirmation dialog in the Dynamic Data site I have been blogging about recently. Specifically, I looked at …

  • replacing the browsers default confirm dialog with a jquery thickbox
  • displaying a confirmation message that includes contextual information regarding the row being deleted

Below is a screen shot showing how it turned out. You can read on for the details, or you can download the site and browse the code for yourself. Hopefully DiscountASP will get upgraded to .Net 3.5 SP1 soon so I can get back to providing demos as well …

Download

image

The Default Confirmation Dialog

If you use the Dynamic Data Web Site template to create your DD web site, the List.aspx page template will already include a default delete confirmation dialog that uses the browsers confirm dialog to prompt the user before allowing them to delete a record. Nothing too fancy here, the alert box just displays some static text (the same text is displayed for all rows). If the user clicks the OK button the record is deleted. Here is what that looks like …

image

And the markup for generating this dialog is also very straight forward …

Customizing the Confirmation Message

With just a small code change, we can make use of a few DD features to add some contextual information about the row being deleted to the confirmation message. You can ask DD to retrieve a display string for any of the rows that are bound to your grid. So, with a pretty simple change we can enhance our dialog to include the display string for the row being deleted. Here is a quick example of what this looks like …

image

And here is the markup for generating this …

Notice the change to OnClientClick. Instead of static text, I am asking DD’s MetaTable (the instance the grid is bound to) to retrieve the display string that corresponds to the rows data item. Simple.

So how does DD know what the display string is? Well, you have to tell it. And you have a couple of options when doing this …

  • Override the ToString property on your entity. Below is a partial class for the Northwind Employee entity. DD will detect that I have overridden the ToString method and will use it whenever the display name is requested for an Employee.
[MetadataType(typeof(EmployeeMetadata))] public partial class Employee {     public override string ToString()     {         return string.Format("{0} {1}", this.FirstName, this.LastName);     } }

And this is how this shows up in the dialog …

image

  • Apply the DisplayColumn attribute to your entities metadata class. If you don’t need to do any computations or formatting and just want to return a column value you can apply the DisplayColumnAttribute to your entities meta-class and set the DisplayColumn value to the column value you want to use for display purposes. Below is a quick example where I am using the Customer’s ContactName column as the display value (line 5) …
[Category("People")] [Description("You can use this page to find out what your customers are up to")] [DisplayName("Customers")] //  Use the ContactName column for the display name [DisplayColumn("ContactName")] public class CustomerMetadata {     [DisplayName("ID")]     public object CustomerID { get; set; }     [DisplayName("Company")]     public object CompanyName { get; set; }     [DisplayName("Name")]     public object ContactName { get; set; }     [DisplayName("Title")]     public object ContactTitle { get; set; }       //  Columns I want hidden     [ScaffoldColumn(false)]     public object Fax { get; set; }     [ScaffoldColumn(false)]     public object Phone { get; set; }     [ScaffoldColumn(false)]     public object PostalCode { get; set; }     [ScaffoldColumn(false)]     public object Country { get; set; }     [ScaffoldColumn(false)]     public object Orders { get; set; } }

And this is how this shows up in the dialog …

image

The only caveat here is that if you have applied a custom format to the DisplayColumn using the DisplayFormat attribute, it doesn’t look like this custom formatting will be applied when the display string is retrieved. Probably not a big deal especially since you can apply formatting using the ToString method I mention above, but it is still interesting. Here is a quick example of what I mean …

I have added the DisplayColumn attribute to my Customer metadata class like so …

//  Use the ContactName column for the display name [DisplayColumn("ContactName")] public class CustomerMetadata {}

And applied the DisplayFormat attribute to the ContactName property like so …

[DisplayFormat(DataFormatString = "{0} testing")] public object ContactName { get; set; }

Then when I request the DisplayString for the Customer rows, the testing suffix is not applied …

image

I didn’t expect that. But like I said, it really isn’t a huge deal because you can always use ToString to format the column value.

Plugging in jquery’s Thickbox

And finally, if you wish to use a different dialog box instead of the browsers default you can plug that into the List.aspx page template as well. I choose to use jquery’s thickbox, but if you prefer the AjaxControlToolkit’s ModalPopup you could easily implement that as well. Here is what I did to make use of the thickbox.

  • Add the markup for the grids ItemTemplate. There are 3 main controls in my template, a link that when clicked displays the thickbox, a hidden ASP button control that is used to force the postback that causes the row to be deleted and a hidden panel that displays the delete message for the row.

image

  • Next, I added a bit of code that runs as the grids rows are bound to the data items. I first extract the thickbox hyperlink, hidden delete button, the confirm button and the panel that contains the message. After I have all of these controls I populate the NavigateUrl property on the Hyperlink to include the correct options (including the ClientID of the rows confirmation message) and use the OnClientClick property of the Yes button to issue the delete by causing the hidden delete button to initiate a postback.
protected void RowDataBound(object sender, GridViewRowEventArgs args) {     if (!table.IsReadOnly && args.Row.RowType == DataControlRowType.DataRow)     {         //  track down the controls         HyperLink deleteLink = (HyperLink)args.Row.FindControl("btnDelete");         Button deleteCommand = (Button)args.Row.FindControl("deleteCommand");         Button yes = (Button)args.Row.FindControl("yes");         Panel deleteConfirm = (Panel)args.Row.FindControl("deleteConfirm");           //  point the thickbox at the confirmation panel for this row         const string thickBoxOptionsFormat = "#TB_inline?height=90&width=350&inlineId={0}&modal=true";         deleteLink.NavigateUrl = string.Format(thickBoxOptionsFormat, deleteConfirm.ClientID);           //  when the user clicks OK, locate the hidden Delete button         //  and click it         const string deleteFormat = "$('#{0}').click(); return false;";         yes.OnClientClick = string.Format(deleteFormat, deleteCommand.ClientID);     } }

Conclusion

Again, I am pleased with the flexibility that Dynamic Data provides me. It’s these seemingly simple requirements of providing a custom delete message that I figured would be difficult to do with Dynamic Data.

That’s it. Enjoy!

Read Excel files in Perl and PHP

Relational databases that speak SQL are the data-storage backbone for most developers. Unfortunately, but most of the data that’s created outside the control of the technology caste at a typical workplace is in Excel format. Because of this, being able to procedurally read and write Excel documents with a familiar language can open up a whole world of possibilities for automation and data migration.

Assuming you’re attempting to read and write standard text (Ie. not binary/graphic) data from Excel worksheets, this is actually fairly doable in PHP and Perl.

A recent article by Mike Diehl at Linux Journal peaked my interest in this. He shows off some of the features of the Spreadsheet::ParseExcel Perl module, which can be used to pull data and even formatting information from cells in an Excel worksheet. Once you have your hands on the data, you can do what you want with it: output it to XML, toss it in a database for subsequent querying, or even convert it into other Excel documents (oh, the shame).

Perl Excel Libraries and Information
Spreadsheet:ParseExcel – Read from Excel 95/97/2000 documents
Spreadsheet:WriteExcel – Write to Excel 97/2000/2002/2003 documents
Linux Journal – Reading Native Excel Files in Perl

There are libraries for dealing with native Excel files in PHP as well. The following two seem to be the only options for binary Excel documents.

PHP Excel Libraries
PHP Excel_Reader – Read Excel 95 and 97 documents
Spreadsheet_Excel_Writer – Write Excel 5.0 documents
Reading and Writing Spreadsheets with PHP

With the most recent version of Excel, there is an XML file format option that will allow you to read and write data in a worksheet by directly interacting with the saved file’s DOM. IBM has a document that details doing this with PHP, and it would be straightforward to apply this technique to Perl as well.

Read/Write XML Excel Data in PHP

Finally, if all you need to do is output a document that can be read in Excel, a standard CSV-format file will usually do the trick. Escaping can be a bit tricky, however, and my preferred format has become a plain-old HTML table. Just create a file that contains a TABLE element (no BODY or HTML tags necessary), with any number of TR rows and html-escaped data in the TDs, and save it out. If you use the XLS file extension, it will open directly in Excel with a double-click and Excel never seems to mind reading in the data.

Do you have any other Excel programming hacks? Give us a shout in the comments.

Frank’s Workbench – Project of the Week

This week’s project comes from Frank (yep, the Woodcraft guy from Ep. 62). Let’s hear what he has to say:

Well, I finally completed my workbench. I would love to have a typical European style bench with a large twin screw vice on the side, but I have neither the space nor the funds. Furthermore, I needed a bench that I can easily move by myself, yet is strong enough to work with mortising chisels or hand planes. Also, because of my height, I prefer a bench that stands just a little higher than most.

This bench turned out to be a pretty good compromise. Its design revolves around the Zyliss vice and Veritas Bench Dogs / Wonder Dogs / Surface Clamp. My father purchased a Zyliss vice back in the 70’s and I have been very impressed with them ever since. New, they tend to be pretty expensive but if you keep your eyes open they are quite reasonable on eBay. I now have four of them.

The light wood is Alder and the darker is Eucalyptus. The Eucalyptus is not only beautiful but also tough as nails. I will say that if I were to do it again, I would replace the Alder with Hard Maple. The Alder is softer than I expected. I made the feet out of Ash to handle the abuse of being moved around. All of the joinery is either pairs of 10×50mm Dominos or Miller dowels. I finished it with Danish Oil and several coats of wax.

Episode 62- Gadget Station (Pt. 5)

Download Low Resolution
Download High Resolution

 

Road Trip! I was originally convinced that the Gadget Station would call for knife hinges. But just for fun I decided to take a trip to my local Woodcraft to see what they might suggest. Well, surprise surprise! I discovered a hinge that I had never noticed before. The Soss Invisible Hinge. I actually like this hinge better and I think it will suit this application perfectly. I hope you enjoy this little review of common hinges with our friend Frank Galloway, at the Chandler, AZ Woodcraft Store.

Links:

WOODSMITH: Adjustable Clamping Jig

Using heavy, bulky pipe or bar clamps to glue up small panels and assemblies is not a good match. You need a clamping method that’s a better fit to the job.

PhotoMy solution to this problem is the adjustable clamping jig you see in the photo above.The jig uses two parallel, pivoting arms to trap the workpieces. Clamping pressure is then applied by driving wedges between the arms and a pair of adjustable dowels. It’s both effective and very easy to use.

DrawingThe drawings at right and below show how the jig is constructed. The two arms are bolted into pivot holes near the outside edge of the 3/4? plywood base. An arc of 1/2?-dia. dowel holes radiates from each edge to provide the adjustability. Add a couple of dowels and a pair of wedges and you’re in business.

Drawing

Good woodworking,

Ted Raife
Online Editor, Woodsmith

Create Separate User Profiles in Google Chrome [How To]

The Digital Inspiration blog points out that new-browser-on-the-block Google Chrome shares one thing with Firefox 3 not mentioned in many press reports—a history-aware address bar, or "Awesome Bar," that can create some red-faced moments on a shared computer. If more than one person on your system is switching to Chrome, and you don't feel like staying in Incognito Mode all the time, creating a new profile in Chrome requires manually creating a folder in Chrome's application data folder, but that's all there is to it. Vista and XP users, hit the link below for help finding your Chrome profiles folder, and then creating a custom shortcut to launch your own Chrome without leaving tracks behind on others.

HOWTO – reset a lost Ubuntu password

I loaded one of my test Ubuntu virtual machines today (one that I hadn’t used for a month) and, surprise, I had forgotten the password. This sort of thing happens from time to time, and if you’re new to Linux, it can be a little disconcerting.

Loosing your root password isn’t the end of the world, though. You’ll just need to reboot into single user mode to reset it. Here’s how to do it on a typical Ubuntu machine with the GRUB bootloader:

Boot Linux into single-user mode

  1. Reboot the machine.
  2. Press the ESC key while GRUB is loading to enter the menu.
  3. If there is a ‘recovery mode’ option, select it and press ‘b’ to boot into single user mode.
  4. Otherwise, the default boot configuration should be selected. Press ‘e’ to edit it.
  5. Highlight the line that begins with ‘kernel’. Press ‘e’ again to edit this line.
  6. At the end of the line, add an additional parameter: ‘single’. Hit return to make the change and press ‘b’ to boot.

Change the admin password
The system should load into single user mode and you’ll be left at the command line automatically logged in as root. Type ‘passwd’ to change the root password or ‘passwd someuser’ to change the password for your “someuser” admin account.

Reboot
Once your done, give the three finger salute, or enter ‘reboot’ to restart into your machine’s normal configuration.

That’s all there is to it. Now just make sure to write your password down on a post-it and shove it somewhere safe like under your keyboard. :)

Marching Penguins: Monitoring Your HPC Cluster

Getting into Ganglia for a scalable and flexible solution to the problem of cluster monitoring.

Copy a Single File to Avoid Re-Activating Windows XP [Tutorial]

The Online Tech Tips site offers up a great tip for anyone reinstalling XP off something other than their original CD—such as a slipstreamed and automated installation—or lacking a net connection to run the activation. Before wiping your system clean, grab a file named WPA.DBL from the System32 directory and save it to a thumb drive or other external media. When you load up your new system, skip registration, enter “Safe Mode” from the boot menu, and drop it back into that System32 folder. Now you’re re-activated and free of nagging. Hit the link below for detailed explanation of each step.


ShopNotes: A smooth finish

I like to use MDF to make shop projects. It’s flat, smooth, and inexpensive. To give the MDF some protection and dress up its bland appearance, I usually paint it. Here are a few tips for getting the best results.

Continue reading “SHOPNOTES: A smooth finish”

WP Like Button Plugin by Free WordPress Templates