Wednesday, March 28, 2012

AjaxControlToolKit HTML Editor IE 9 Copy / Paste Bug

So, if you are reading this BLOG post, you probably already know that there is a bug in the AJAXControlToolKit's HTML Editor which while in IE 9, you cannot perform simple Copy/Paste operations.

This is a HUGE problem!  (Although, if you visit their website, the bug report only has a few votes.  This still boggles my mind!)

Well, as of the time this post was made, there still is no direct fix for this problem.  However, I have found a workaround.

Turns out, you can force a page to render in Compatibility mode for IE 7 or IE 8.  To do so, you need to insert the following META tag into the <HEAD> of your document.

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />

You can also use EmulateIE7 to go to IE7 standards.



There's a gotcha here though!

Turns out, if that META tag isn't the very first tag to be found in the <HEAD> section, it doesn't work.

This isn't a problem for a lot of people, but for us, it was a big problem because we have some "black box" development tools which adds LINK files for styling info to the <HEAD> during page load.  It does this to the top of the tag!  DOH!

But wait!  The fix:

 Protected Sub Page_LoadComplete(sender As Object, e As System.EventArgs) Handles Me.LoadComplete
            Dim forceIE7Compat As New HtmlMeta
            forceIE7Compat.Content = "IE=EmulateIE8"
            forceIE7Compat.HttpEquiv = "X-UA-Compatible"
            Page.Header.Controls.AddAt(0, forceIE7Compat)
 End Sub

This code will execute after the page has finished loading and adds the META tag as the very first element to the HEAD of the page.

Hope this helps someone!

Tuesday, January 10, 2012

Adding Javascript OnClick to ASP.NET Grid View Edit Button

Recently, I had a need to add a javascript onclick event to the edit LinkButton that a GridView display when you set the CommandField and ShowEdit to True.

<asp:CommandField ShowEditButton="True" />

This solution will actually work for any control automagically added by ASP.NET with the CommandField options.

The trick is, it loops through all the rows in the underlying table created by the GridView, examines the cells in those rows for controls, locates the control you are looking for, and then, it can access the attributes of that control.

You will have to be careful here because as you can see from the solutions, it's using the prior knowledge that the only LinkButton in any of the cells is the one we want to access.  If you have more controls, you will need to be a bit more clever about locating the control.  For example, you could specify WHICH cell in the cell array by index or which control in the control array if your LinkButton is always in the same position.


                For Each r As TableRow In Grid.Rows
                    For Each a As TableCell In r.Cells
                        If a.Controls.Count > 0 AndAlso TypeOf a.Controls(0) Is LinkButton Then
                            CType(a.Controls(0), LinkButton).Attributes.Add("onclick", "NoCheck();")
                        End If
                    Next
                Next

Wednesday, October 19, 2011

Uninstalling an MSI that throws an error during uninstall process

I got caught in Catch 22 that I finally solved yesterday.  I'm working on building an MSI package and had installed it on my machine for testing.  When I went to uninstall, I couldn't because of an error in the MSI.

This was a big problem!  I fixed the problem in my MSI, but I couldn't repair or reinstall using the now fixed version because it wanted to remove the old version first.

After hours of searching, I finally found the right command:

msiexec /fv (product code)

/fv forced a reinstall using my new package.  Then, I could uninstall.

Friday, September 23, 2011

ClientScript.RegisterArrayDeclaration doesn't play nice with Upload Panels

Found a new one today!

I had a problem where some javascript arrays were being initialized by ClientScript.RegisterArrayDeclaration on the server side ASP.NET code.  This worked great initially as the array needed to be loaded up during the first call to the page.

However, I got user requests to add more features to the page including adding new elements to the list that that array would populate.  Of course, they don't want screen flicker on the page either, so no full postbacks.  I assumed that by just doing a normal postback, the array registration code would work fine and everything would move forward.

Turns out, if the declaration is part of controls inside of update panels, ClientScript.RegisterArrayDeclaration won't update the array.  It will look to the javascript after the partial postback just as it did before.

It took me a long time to run this down, but in .NET 4, there is a new animal called ScriptManager.RegisterArrayDeclaration that is built to play nice with UpdatePanels.  So, I quickly changed the ClientScript to ScriptMangager, and sweet!  The array would get updated.

But wait, there's more!  Now, the array gets updated but the old data doesn't get rebuilt.  It just builds on top of itself, adding the same elements to the array each postback.  Bad!

So to solve, I added code to set the array to null prior to all the array declaration code:

ScriptManager.RegistlerClientScriptBlock(me.page, me.page.gettype, "code","array = null;",true)

This would clear the array then reload it.

__doPostBack causing Screen Flicker even when set as Asyncpostbacktrigger

Ran into a good one today that made me to start a BLOG.  I run into issues all the time that require fixes.  Sometimes, you can find solutions on the web.  Sometimes, you can't.

I always felt like I should give back to the community that I extract so much from.  So, here's one that I had to reason through with just a little help.

I had a scenario where I needed a button to exist but not allow the user to click it.  The reason is that I needed some javascript to perform a __doPostBack() using that button so that the ASP.NET page would fire its event on post back.  However, I do this in response to some other user actions handled by javascript.  Thus, to prevent the user from clicking the button, I set the visibility property of the button to false.

<asp:button id="someButton" runat="server" visible="false" />

So, my javascript would fire the event correctly.

__doPostBack('someButton',null);

And my ASP.NET page would capture the event correctly.

The problem I ran into though was that even though my button was inside an UpdatePanel, I would still get screen flicker.  I tried adding the button as an Asyncpostbacktrigger as the recommendation of many on-line searches.

<asyncpostbacktrigger controlid="someButton" />

The screen flicker continues.  I'm annoyed at this point.  How could the event be firing, be being captured, be an asyncpostbacktrigger, and still causing screen flicker?

The answer turns out that the UpdatePanel triggers can't "see" a control that has its visibility set to false, most likely because the control never makes it to the page.  Thus, it performs a full postback.

The simple solution?

<asp:button id="someButton" runat="server" visible="true" style="display : none;">

Solved!