passing a non-databound column to javascript

R

rlm

I have a gridView with a template field that looks like this

<asp:TemplateField HeaderText="">
<ItemTemplate>
<a href="javascript:OpenHelp('<%# Eval("Status") %>')">
<img alt="Click for help." src="help\help.gif" border="0px"
width="12px"/>
</a>
</ItemTemplate>
</asp:TemplateField>

This works great in a test grid where status is actually bound to the
database. However in the real case Status is not bound but is a column
populated based on complex logic from many fields. I know the whole Eval this
is for databound stuff, but how do I pass it when it is not databound? The
"Status" column is another template field with header text = "Status".
 
C

Chad Scharf

You can perform any operations using the <%# %> using page or static utility
classes/methods that you could using, say, <%= %> or in your code behind.
Perhaps the best solution would be to do something like this:

public static class MyDataManager
{
public static string GetComplexStatus(object val1, object val2, object
val3)
{
// Do any normal logic you would do to determine what the status is
// then return it to the caller.
return string.Format("{0} : {1} : {2}", val1, val2, val3);
}
}

Then on your page, you could call this like:

<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<a href="javascript:OpenHelp('<%#
MyDataManager.GetComplexStatus(Request.Url, Eval("MyField1"),
this.protectedPageVariable1) %>')">
<img alt="Click for help." src="help\help.gif" border="0px"
width="12px"/>
</a>
</ItemTemplate>
</asp:TemplateField>

This example shows pulling values that are not necessarily databound, but
perhaps are page variables (protected +), properties, other methods, static
methods or properties, and maybe even another data bound field.

Hope this helps.
 
R

rlm

Chad, thanks. Is there a way to simply reference the value/string that is
already in the table cell on the rendered page, and pass that to javascript?
 
C

Chad Scharf

Sure...

In your header, or somewhere before the databound control (repeater,
datagrid, etc), place something like this:

<script type="text/javascript">
<!--
var myVal;
//-->
</script>

Then inside of your <ItemTemplate />:

....
<ItemTemplate>
<script type="text/javascript">
<!--
myVal = '<%# Eval("ColumnName") %>';
//-->
</script>

<%-- Or you could use it in this fashion --%>
<asp:Button runat="server" ID="myButton" Text="Click Me"
OnClientClick='<%# string.Format("alert('{0}');return false;",
Eval("ColumnName")) %>' />
</ItemTemplate>
 
R

rlm

Chad,
I will try these suggestions out later today, but I don't see how this last
one is much different than my first post "javascript:OpenHelp('<%#
Eval("Status") %>')" which does not work. The Eval on the non bound Template
Field did not work. I guess I am still missing something in my understanding.
 
R

rlm

This line

myVal = '<%# Eval("Status") %>';

produces this error

DataBinding: 'System.Data.DataRowView' does not contain a property with the
name 'Status'.

because the field is not databound.
 
C

Chad Scharf

OK, I misunderstood the actual issue you were having; my apologies. I've run
into this issue a few times in the past when binding a DataTable or DataSet
to a databound control.

Are you using a SqlDataSource control, binding via code behind, etc? Please
ensure that the column "Status" is in your select list, if it is not, then
your code below would fail with this error. If you are using Typed datasets,
please ensure that the property settings for the Status column is
pass-through to the associated DataView, especially if it is a calculated
column or relies on an expression for its value.

Set a break-point in the Control_ItemDataBound event and explore your item's
datasource to ensure this column is present.

If the column/value is indeed there, you may as I have done in the past use
a typed expression to retrieve it and see how that works for you, e.g.:

<%# ((System.Data.DataRowView)Container.DataItem).Row["Status"] %>

Thanks,
 
C

Chad Scharf

To expand on this a little further going back, I do want to point out that
your ItemTemplate is still a DataBound field, even if it is keying off of the
"Status" column which is not directly from your Database itself.

The Eval(); method is intended to pull a property or reference point from a
data item, which inheritly is the assigned object from the enumerator bound
to your control. This object, whether it is a DataRowView or perhaps a custom
class, must contain the property or accessor for the Eval("") expression you
provided, if it does not you will reiceve that databinding error.

It sounds as if your "Status" column is a calculated field within a typed
DataSet, or is added via another method in your code. If this is true, use
the debugger to trace your databinding events to ensure this column is being
generated properly, that the AcceptChanges(); method is called on your
DataSet - OR - for pending changes or for safety sake, use the .Select()
method on your DataTable rather than allowing the DataBinding evaluator call
the DataRowView:

....
DataRow[] source = myTable.Select();
if (source.Length > 0)
MyDataBoundControl.DataSource = myTable.Select();
else
MyDataBoundControl.DataSource = null; // zero length collections not
allowed
MyDataBoundControl.DataBind();
....

Let me know what you find.

--
Chad Scharf
_______________________________
http://www.chadscharf.com


Chad Scharf said:
OK, I misunderstood the actual issue you were having; my apologies. I've run
into this issue a few times in the past when binding a DataTable or DataSet
to a databound control.

Are you using a SqlDataSource control, binding via code behind, etc? Please
ensure that the column "Status" is in your select list, if it is not, then
your code below would fail with this error. If you are using Typed datasets,
please ensure that the property settings for the Status column is
pass-through to the associated DataView, especially if it is a calculated
column or relies on an expression for its value.

Set a break-point in the Control_ItemDataBound event and explore your item's
datasource to ensure this column is present.

If the column/value is indeed there, you may as I have done in the past use
a typed expression to retrieve it and see how that works for you, e.g.:

<%# ((System.Data.DataRowView)Container.DataItem).Row["Status"] %>

Thanks,

--
Chad Scharf
_______________________________
http://www.chadscharf.com


rlm said:
This line

myVal = '<%# Eval("Status") %>';

produces this error

DataBinding: 'System.Data.DataRowView' does not contain a property with the
name 'Status'.

because the field is not databound.
 
R

rlm

I have not been able to force the "Status" field into the default view. There
is no such fielld in the table, and debugging has not helped me.

Anyone can reproduce this in less than three minutes(if they already have a
database to connect to) with the following steps

1. create new web application
2. drop on a grid view
3. Choose datasource (sql)
4 connect to any table and select some fields
5. On gridView tasks choose Edit Columns
6. Add a template field
7. Change its header text to status
8. use RowDataBound event to set the value in that field with something like
this
e.Row.Cells[2].Text = "happy";

9. Pass that fields value to a javascript function like this
<ItemTemplate>
<a href="javascript:OpenHelp('<%# Eval("Status") %>')">
Text
</a>
</ItemTemplate>
 
C

Chad Scharf

Oooh, that's what you meant by "not databound." That makes sense now and so
does the exception and what you're trying to accomplish.


You can do this many ways, however the easiest is to do the following:

e.Row.Cells[2].Text = string.Format("<a href=\"\"
onclick=\"javascript:OpenHelp('{0}');return false;\">{0}</a>", status);

When you set the Text of a cell in a DataBound row inside of a GridView, you
would be replacing the content of that cell (inlcuding whatever the
ItemTemplate specified) anyways.

Other ways you can accomplish this are with protected page level variables
to store the databound value in, then in your ItemTemplate use the <%# myVar
%> syntax instead of Eval("").

Thanks,
 
R

rlm

Chad, thanks so much! Bless you. I am sorry I wasn't more clear at the
beginning, but I did learn some other things from your other posts.

I have that working in the little sample app. Now I will transfer it to the
real app and figure out the syntax of adding in the image embedded into the
anchor tag.
<img alt="Click for help." src="help\help.gif" border="0px" width="12px"/>

I just have one small question about your answer which I don't understand.
e.Row.Cells[2].Text = string.Format("<a href=\"\"
onclick=\"javascript:OpenHelp('{0}');return false;\">{0}</a>", status);

What is the "return false;" for?
 
R

rlm

In case anyone else runs into this post and wnats an answer without reading
all the chain above heres the quick answer that was a result of Chad
patiently persisting until I stopped confusing him, and then he graciously
gave the answer.

Anyone can reproduce this in less than three minutes(if they already have a
database to connect to) with the following steps
1. create new web application
2. drop on a grid view
3. On gridView tasks choose datasource (sql)
4 connect to any table and select some fields
5. On gridView tasks choose Edit Columns
6. Add a template field
7. Change its header text to status
8. use RowDataBound event to set the value in that field with something like
this e.Row.Cells[2].Text = "happy";
9. Pass that fields value to a javascript function like this in the aspx
<ItemTemplate> <a href="javascript:OpenHelp('<%# Eval("Status") %>')"> Text
</a> </ItemTemplate>

You will get an error like this.

System.Web.HttpException was unhandled by user code
Message="DataBinding: 'System.Data.DataRowView' does not contain a
property with the name 'Status'."

The answer Chad gave, which works, is to send the javascript in from the
RowDataBound code behind in addition to the text of the template field. like
this:

e.Row.Cells[2].Text = string.Format("<a href=\"\"
onclick=\"javascript:OpenHelp('{0}');return false;\">{0}</a>", status);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top