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 ...

[Update: 9/21/2008]: Added live demo link  

Download | Live Demo

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 ...

   1: <asp:LinkButton ID="DeleteLinkButton" runat="server" CommandName="Delete"
   2:     CausesValidation="false" Text="Delete"
   3:     OnClientClick='return confirm("Are you sure you want to delete this item?");'
   4: />

 

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 ...

   1: <asp:LinkButton ID="DeleteLinkButton" runat="server" CommandName="Delete"
   2:     CausesValidation="false" Text="Delete"
   3:     OnClientClick='<%# string.Format("return confirm(\"Are you sure you want to delete {0}?\");", table.GetDisplayString(GetDataItem())) %>'                                
   4: />

 

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.
   1: [MetadataType(typeof(EmployeeMetadata))]
   2: public partial class Employee
   3: {
   4:     public override string ToString()
   5:     {
   6:         return string.Format("{0} {1}", this.FirstName, this.LastName);
   7:     }
   8: }

 

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) ...
   1: [Category("People")]
   2: [Description("You can use this page to find out what your customers are up to")]
   3: [DisplayName("Customers")]
   4: //  Use the ContactName column for the display name
   5: [DisplayColumn("ContactName")]
   6: public class CustomerMetadata
   7: {
   8:     [DisplayName("ID")]
   9:     public object CustomerID { get; set; }
  10:     [DisplayName("Company")]
  11:     public object CompanyName { get; set; }
  12:     [DisplayName("Name")]
  13:     public object ContactName { get; set; }
  14:     [DisplayName("Title")]
  15:     public object ContactTitle { get; set; }
  16:  
  17:     //  Columns I want hidden
  18:     [ScaffoldColumn(false)]
  19:     public object Fax { get; set; }
  20:     [ScaffoldColumn(false)]
  21:     public object Phone { get; set; }
  22:     [ScaffoldColumn(false)]
  23:     public object PostalCode { get; set; }
  24:     [ScaffoldColumn(false)]
  25:     public object Country { get; set; }
  26:     [ScaffoldColumn(false)]
  27:     public object Orders { get; set; }
  28: }

 

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 ...

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

 

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

   1: [DisplayFormat(DataFormatString = "{0} testing")]
   2: 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.
   1: protected void RowDataBound(object sender, GridViewRowEventArgs args)
   2: {
   3:     if (!table.IsReadOnly && args.Row.RowType == DataControlRowType.DataRow)
   4:     {
   5:         //  track down the controls
   6:         HyperLink deleteLink = (HyperLink)args.Row.FindControl("btnDelete");
   7:         Button deleteCommand = (Button)args.Row.FindControl("deleteCommand");
   8:         Button yes = (Button)args.Row.FindControl("yes");
   9:         Panel deleteConfirm = (Panel)args.Row.FindControl("deleteConfirm");
  10:  
  11:         //  point the thickbox at the confirmation panel for this row
  12:         const string thickBoxOptionsFormat = "#TB_inline?height=90&width=350&inlineId={0}&modal=true";
  13:         deleteLink.NavigateUrl = string.Format(thickBoxOptionsFormat, deleteConfirm.ClientID);
  14:  
  15:         //  when the user clicks OK, locate the hidden Delete button
  16:         //  and click it
  17:         const string deleteFormat = "$('#{0}').click(); return false;";
  18:         yes.OnClientClick = string.Format(deleteFormat, deleteCommand.ClientID);
  19:     }
  20: }

 

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!


TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/150

Listed below are links to weblogs that reference Dynamic Data - Customizing the Delete Confirmation Dialog:

» Matt Berseth: Dynamic Data - Customizing the Delete Confirmation Dialo from DotNetKicks.com
You've been kicked (a good thing) - Trackback from DotNetKicks.com [Read More]

» Matt Berseth's ASP.NET Demo Gallery from J├╝rgen Gutsch
Der .NET Entwickler Matt Berseth hat unter http://mattberseth2.com/demo/ eine umfangreiche Demo Gallery [Read More]

Comments


Nice! Great tip.

Matt --

These are really useful posts as we are working with DD on several projects at work that lend themselves to it.

Thank you very much and please keep it going!

Marc

Posted by: Ajay Sharma on September 8, 2008 05:22 AM

Hey Matt,

All of your posts are awesome.
I like your content very very much.

Thanks a lot for sharing.

Posted by: redsquare on September 8, 2008 05:35 AM

BlockUI may have been a better choice for the dialog

Your code will fail if there is a single-quote in the data being displayed in the referenced field.

Posted by: Darkwing on September 8, 2008 09:53 AM

How can DD be used in a 3 tier (web, app, db) environment ?

Posted by: Petr Snobelt on September 10, 2008 02:41 AM

Hi Matt,
nice post (especially 1 part).
But I see 2 problems:
1. Accessibility without javascript
2. It adds lot of markup to each table row.

I think better solution is to create markup dynamically by JS after page loads (or better after button is clicked).
Or owerride aleft function like
http://slayeroffice.com/code/custom_alert/

Thanks for nice article

Matt,

I don't think you are getting a true modal from thickbox with your code at the moment. When I click anywhere on the screen the popup will disappear. I haven't found a fix yet.

Thanks for all your great work.

Bill

Posted by: Sreedhar Vankayala on September 17, 2008 05:19 PM

Hi Matt,

Are you planning to have code combination of

Dynamic Data, Ajaxtoolkit - Tabs, collapsible panel, Confirm popup (your earlier post)?

Regards

Sreedhar Vankayala

Posted by: Rakesh S on September 23, 2008 10:40 AM

It seems when I click on paging in my case page 3 and clicked on 'Simons bistro', it popuped up showing different name in dialog box.

Matt,

I finally had a chance to look at the jQuery in the Thickbox plugin. Commenting out the following line took care of the modal popup disappearing when the overlay was clicked:

$("#TB_overlay").click(tb_remove);

It occurs in two places. One is a hack for IE6.

Bill

I use this

OnClientClick=''

instead of overriding ToString()

Thanx for your great article

Matt>> I choose to use jquery's thickbox, but if you prefer the AjaxControlToolkit's ModalPopup you could easily implement that as well.

For those who have already given Ajax Toolkit a flick, I'd recommend "jQuery UI Dialog" instead of Thickbox or jqModal.

jQuery UI is the standard. Thickbox / jqModal are just plug-ins.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Consulting Services

Yep - I also offer consulting services. And heck, I'll do just about anything. If you enjoy my blog just drop me an email describing the work you need done.

Recent Comments

  • Asheesh Soni wrote: Matt>> I choose to use jquery's thickbox, but if you prefer the AjaxControlToolkit's ModalPopup you ...
  • Barbaros wrote: I use this OnClientClick='' instead of overriding ToString() Thanx for your great article...
  • OldBoy wrote: Looks like you got your wish Matt ;) <a href="http://www.hanselman.com/blog/jQuerytoshipwithASPNETM...
  • Bill Beckelman wrote: Matt, I finally had a chance to look at the jQuery in the Thickbox plugin. Commenting out the follo...
  • Rakesh S wrote: It seems when I click on paging in my case page 3 and clicked on 'Simons bistro', it popuped up show...
  • Sreedhar Vankayala wrote: Hi Matt, Are you planning to have code combination of Dynamic Data, Ajaxtoolkit - Tabs, collapsibl...
  • Bill Beckelman wrote: Matt, I don't think you are getting a true modal from thickbox with your code at the moment. When I...
  • Petr Snobelt wrote: Hi Matt, nice post (especially 1 part). But I see 2 problems: 1. Accessibility without javascript ...