Registering client script block for a custom control

Apr 3, 2009 at 9:57 AM

Hi, I've just started using PartialUpdatePanel and I'm impressed - it does exactly what I want almost straight out of the box. I'm having a problem though, in trying to successfully register a client script block from within a custom control.

I've got a UserControl set up as a panel to display search results (UCSearchResults). Within the panel there are a couple of standard asp:Table and asp:Label controls, and then an instance of a custom extended DataGrid, called hdg:HighlightDataGrid, which displays the actual results. I didn't write the extended control, but I have modified it quite a bit. The HDG works fine on its own, and for the most part it works great within the PartialUpdatePanel setting, but two of the extended features aren't working quite right.

The first is mouseover highlighting. In the OnPreRender method a JavaScript string is created which contains a function to change the background colour of a row when the mouse is over it, and to change it back when the mouse moves off it. In the original, this is accomplished with the code:

if (RowHighlightColor != Color.Empty && !Page.IsClientScriptBlockRegistered(SCRIPT_KEY))
{ Page.RegisterClientScriptBlock(SCRIPT_KEY, String.Format(SCRIPT, RowHighlightColor.R, RowHighlistColor.G, RowHighlightColor.B)); }
I've read that I have to use ScriptManager.RegisterClientScriptBlock to get it working with the PartialUpdatePanel, but I've tried it a few different ways and it just won't go. No matter what, the JavaScript throws an error, complaining that it can't find the changeColor function. Is there a way to get this functionality in the panel?

The second problem probably has to be resolved within the UserControl itself - clicking on a row should redirect the user to a page dependent on the value in a cell in that row. That was accomplished with the Response.Redirect method, but that won't work now that it's an asynchronous page component, and it instead returns the raw HTTP status string from the server. It should just be a matter of rewriting the method that is called, but I'm not sure how to pass the request up to the page level from the panel.

Now, I'm not fantastic with ASP.NET or C#, so I don't really know where to start trying to fix these problems. I'd appreciate any help anyone can offer, and if you need more info I'm glad to provide it.
Coordinator
Apr 3, 2009 at 10:04 AM
Hi Zetten,

I am glad, you like the control.
Please try to use ScriptManager.RegisterClientScriptBlock instead of Page.RegisterClientScriptBlock (IsClientScriptBlockRegistered will then become obsolete too).
I guess this should solve your problems.

Let me know if this works for you, otherwise I'll take a deeper look.

Best regards,
Stefan
Coordinator
Apr 3, 2009 at 10:06 AM
Edited Apr 3, 2009 at 10:19 AM
The Response.Redirect issue is covered in my RedirectSample and also in this Thread http://partialupdatepanel.codeplex.com/Thread/View.aspx?ThreadId=36123
Let me know if this helps.
Apr 3, 2009 at 10:16 AM

Thanks for the very quick response!

I found the thread you mentioned a minute after I posted this, and that's working fine now - one problem down.

Using ScriptManager.RegisterClientScriptBlock isn't working for me. It could be my syntax or positioning though:

if (RowHighlightColor != Color.Empty)
{ ScriptManager.RegisterClientScriptBlock(this, GetType(), SCRIPT_KEY, StringFormat(SCRIPT, RowHighlightColor.R, RowHighlightColor.G, RowHighlightColor.B), true); }

This code is located in the OnPreRender method of the HighlightDataGrid control. Should it perhaps be pointed one level up so it's working at the same level as the UserControl, or would that not matter? I've tried using this.Parent and this.Parent.GetType() as the first two arguments with no success.

Coordinator
Apr 3, 2009 at 10:22 AM
Hi Zetten,

what does SCRIPT contain?
Is it a full function or just a function call?
If it is a function call, where you you register the function?

You can safely use RegisterClientScriptBlock in DataGrid's OnPreRender. It does not matter where the call is located.

Regards,
Stefan
Apr 3, 2009 at 10:25 AM
						const string SCRIPT = @"";
Apr 3, 2009 at 10:28 AM
Hit post accidentally there. SCRIPT contains:
const string SCRIPT = @"<script language=""Javascript"">

var lastColorUsed;

var lastColorUsed;

function changeColor(row, highlight) {{
if (highlight) {{
lastColorUsed = row.style.backgroundColor;
row.style.backgroundColor = '#{0:X2}{1:X2}{2:X2}';
row.style.cursor = 'pointer';
}}
else {{
row.style.backgroundColor = lastColorUsed;
}}
}}

</script>";
Or thereabouts (filtering in the forum software interfered a bit). The function call is added to the row item in the CreateItem() method, setting attributes for onmouseover and onmouseout.
Coordinator
Apr 3, 2009 at 10:31 AM
ah ok, I see.
One mistake is that RegisterClientScriptBlock(..., true) automatically adds <script>-Tags.
So the ones you add are redundant. Maybe that is the cause why the function is not found at runtime.
How do you put a refrerence to the current row into changeColor?
Apr 3, 2009 at 10:44 AM
The DataGrid.CreateItem method is overridden with:
item.Attributes["onmouseover"] = "javascript:changeColor(this, true);"; 
and a similar attribute for onmouseout.

And yes, you're exactly right! Removing the redundant <script> tags fixes it - I feel stupid for missing it, but thanks so much for pointing it out.