Asp.Net and Shadowbox - asp.net

Trying to pop up an IFrame Shadowbox with Jquery from an asp:gridview datarow. I can't get the proper quotes into the string:
<asp:ImageButton ID="btnEdit" runat="server"
OnClientClick='<%# "javascript:popAccount(\'"+
Eval("id", "Popup.aspx?id={0}")+"\');" %>' />
Parser Error Message: The server tag is not well formed.
Without the escaped single quotes (cannot work, but parses properly):
<asp:ImageButton ID="btnEdit" runat="server"
OnClientClick='<%# "javascript:popAccount("+
Eval("id", "Popup.aspx?id={0}")+");" %>' />
Client-side HTML, as expected:
onclick="javascript:popAccount(Popup.aspx?id=3ce3b19c-1899-4e1c-b3ce-55e5c02f1);"
How do I get quotes into the Javascript?
Edit: added solution. This not very generic, since the databound types must be known in order to access the id property. The key (as defined in the GrodView's DataKeyNames parameter) does not seem to be exposed in the event argument. But it works.
protected void editGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
// do not look at header or footer
if (e.Row.RowType == DataControlRowType.DataRow)
{
ImageButton btn = e.Row.FindControl("btnPopup") as ImageButton;
if (btn != null)
{
btn.OnClientClick =
"javascript:popAccount('EditAccountPopup.aspx?"+
Constants.acctidParam+"="+
((tb_account)(e.Row.DataItem)).id.ToString()+"');";
}
}

Pick up the ImageButton in the GridView's rowdatabound event in the codebehind, and add the property from there.
But are you sure you need to use a server control? How about just a plain image? If you're "replacing" the click-behaviour of the ImageButton, it doesn't seem like you need it at all.
Update:
For the code-behind solution, I coded up this little sample (in VB.NET, sorry):
Private Sub gridview1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gridview1.RowDataBound
Select Case e.Row.RowType
Case DataControlRowType.DataRow
Dim btnEdit As ImageButton = CType(e.Row.Cells(0).FindControl("btnEdit"), ImageButton)
Dim strID As String = CType(e.Row.DataItem, Guid).ToString
btnEdit.Attributes.Add("onclick", String.Format("javascript:popAccount('Popup.aspx?id={0}');", strID))
End Select
End Sub
However, I'd still recommend you go with a simpler aproach, jQuery is excellent here. No
need for any code in your codebehind:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">
$(document).ready(function() {
$("img.edit").click(function() {
var sID = this.id.replace('btnEdit_', '');
alert(sID); // Add your popup opening logic here...
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="gridview2" AutoGenerateColumns="false" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<img id="btnEdit_<%#Container.DataItem %>" class="edit" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>

If you want to keep your code the way it is, why not just do this?
<asp:ImageButton ID="btnEdit" runat="server"
OnClientClick='<%# "javascript:popAccount(&quot"+
Eval("id", "Popup.aspx?id={0}")+"&quot);" %>' />

Related

Open new dynamic window within gridview dataview?

I have a gridview (called grdSearchResults) that contains links to pdfs. The pdf url's are returned from the database but I'm not sure how to add the url to an imagebutton control within the gridview.
Here's my codebehind:
List<SearchResults> search = _searchRepository.GetFactFileSearchResults(results);
grdSearchResults.DataSource = search;
grdSearchResults.DataBind();
And here's my aspx page code:
<asp:TemplateField HeaderText="FILE TYPE" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:ImageButton runat="server" ID="_imgbtnPreview" OnClientClick="<%# Container.DataItem("DownloadUrl") %>" ImageUrl="~/images/fileType_pdf.png" />
</ItemTemplate>
But this thows an error ("The server tag is not well formed") Any idea how to fix this? Thanks
I assume you want to call a javascript function OnClientClick. But you haven't showed us it so it's difficult to help.
You can also set the ImageButton's ImageUrl in RowDataBound (which i normally prefer):
protected void grdSearchResults_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView rv = (DataRowView) row.DataItem;
ImageButton imgbtnPreview = (ImageButton)e.Row.FindControl("_imgbtnPreview");
imgbtnPreview.ImageUrl = rv.Row.Field<String>("DownloadUrl");
}
}
Your OnClientClick should be using single quote in the outer
OnClientClick='<%# Container.DataItem("DownloadUrl") %>'
And the image can be
<asp:Image runat="server" ID="x" ImageUrl='<%# String.Format("~/{0}", Eval("ImageUrl")) %>' />

Dropdownlist in a repeater, selected index changed not working

I have a repeater with a dropdownlist in it. When a user changes its index, I would like a label to change its value. (the ddlSizes values come from a MySQL DB)
Sizes.aspx
<asp:DropDownList ID="ddlSizes" runat="server" AutoPostBack="True" DataSourceID="objdsSizes" DataTextField="SizeName" DataValueField="SizeID" />
<asp:Label ID="lbldummy" runat="server" Text=""></asp:Label>
Sizes.aspx.vb
Protected Sub ddlSizes_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlSizes.SelectedIndexChanged
lbldummy = ddlSizes.value
End Sub
But the ddlSizes.SelectedIndexChanged isn't recognized. So the value of lbldummy won't change.
Any suggestions? Thank you.
You will want to create the handler for the DropDownList, within this you need to have code which will convert the sender into a DropDownList then get the parent control and convert it into the RepeaterItem. From this you can then reference any other controls within the RepeaterItem
Public Sub ddlSizes_SelectedIndexChanged(sender As Object, e As EventArgs)
Dim ddlSizes As DropDownList = DirectCast(sender, DropDownList)
Dim ri As RepeaterItem = DirectCast(ddlSizes.Parent, RepeaterItem)
Dim lbldummy As Label = DirectCast(ri.FindControl("lbldummy"), Label)
lbldummy.Text = ddlSizes.SelectedValue
End Sub
Then on your ddlSizes DropDownList add OnSelectedIndexChanged="ddlSizes_SelectedIndexChanged" and make sure it has AutoPostBack="True" set
Text is probably the default property, but I'd still specify it:
lbldummy.Text = ddlSizes.value
but for this, you really don't need to do a postback, you can accomplish this through Javascript as well. doing something like this:
<asp:DropDownList ID="ddlSizes" runat="server" onchange="return ddlSizes_change(this);" DataSourceID="objdsSizes" DataTextField="SizeName" DataValueField="SizeID" />
function ddlSizes_change(dropdown)
{
document.getElementById('<%= lbldummy.ClientID %>').innerHTML =
dropdown.options[myindex].value
return true;
}
Here's an example (C# but easily adaptable to VB.NET). Notice how inside the DdlSizes_SelectedIndexChanged I use FindControl to find the corresponding label:
<%# Page Language="C#" %>
<script type="text/c#" runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
rep.DataSource = Enumerable.Range(1, 5);
rep.DataBind();
}
}
protected void DdlSizes_SelectedIndexChanged(object sender, EventArgs e)
{
var ddl = (DropDownList)sender;
var lbl = (Label)ddl.FindControl("lbldummy");
lbl.Text = ddl.SelectedValue;
}
</script>
<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="Form1" runat="server">
<asp:Repeater ID="rep" runat="server">
<ItemTemplate>
<asp:DropDownList ID="ddlSizes" runat="server" AutoPostBack="True" OnSelectedIndexChanged="DdlSizes_SelectedIndexChanged">
<asp:ListItem Value="1" Text="item 1" />
<asp:ListItem Value="2" Text="item 2" />
<asp:ListItem Value="3" Text="item 3" />
</asp:DropDownList>
<asp:Label ID="lbldummy" runat="server" />
</ItemTemplate>
</asp:Repeater>
</form>
</body>
</html>

Update Panel and triggers from a repeater control

Hi I found code similiar to the following online. It's seems really great for getting a button buried in a repeater control to trigger a full cycle back to the server.
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<%=DateTime.Now.ToString() %>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="HiddenButton" />
</Triggers>
</asp:UpdatePanel>
<!--Make a hidden button to treat as the postback trigger-->
<asp:Button ID="HiddenButton" runat="server" Style="display: none" Text="HiddenButton" />
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<ItemTemplate>
<!--when cick the button1, it will fire the hiddenButton-->
<asp:Button ID="Button1" Text="Trigger" CommandArgument='<%# Eval("Id") %>' OnClientClick="$get('HiddenButton').click();return false;"
runat="server" />
</ItemTemplate>
</asp:Repeater>
It uses a hiddenButton to achieve this by hooking the click event of the original button to this one. However my addition to this was the setting of the CommandArgument for the button. I would also need it to be set for the HiddenButton.
Does anyone know a way of going about this?
First I will like to explain the Disadvantage of using the Update Panel using the very same example posted by you.
Below is the Original Code
Output
To display the 22 character string you can check how much data is being received and sent to server. Just imagine following
If you would consider send each request to Database using Update Panel and your GridView is in Update Panel!!!!!!
Suppose you would use ViewState data for each request and with GridView Inside the Update Panel.
Both the above techniques are worst as per my understanding.
Now I will describe you Page Methods
Page Method over Update panel
Page Methods allow ASP.NET AJAX pages to directly execute a Page’s Static Methods, using JSON (JavaScript Object Notation). Instead of posting back and then receiving HTML markup to completely replace our UpdatePanel’s contents, we can use a Web Method to request only the information that we’re interested.
Sample Code
Output
Hope this clearly explains the difference of usage.
Answer to the original Query
You have to register the ItemDataBound event of the below Repeater and use below code for it.
Code Behind
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
Button btn = (Button)e.Item.FindControl("Button1");
btn.OnClientClick = string.Format("SubmitButton('{0}');return false;"
, HiddenButton.ClientID);
}
}
JavaScript
<script type="text/javascript">
function SubmitButton(btn)
{
$("#" + btn).click();
}
</script>
//Alternative
<script type="text/javascript">
function SubmitButton(btn)
{
document.getElementById(btn).click();
}
</script>
Reference & Here
Your HiddenButton control is a server control but you are trying to access it in JQuery using it's ASP.Net ID,
<asp:Button ID="Button1" Text="Trigger" CommandArgument='<%# Eval("Id") %>' OnClientClick="$get('**HiddenButton**').click();return false;"
runat="server" />
A quick way to fix it is to make a separate function,
<script type="text/javascript">
function SubmitButton(btn)
{
$get("#" . btn).click();
}
</script>
and change your button code to ,
<asp:Button ID="Button1" Text="Trigger" CommandArgument='<%# Eval("Id") %>'
runat="server" />
In code behind, in repeater's ItemDataBound event, find the button and HiddenControl and set Button1's OnClientClick property,
Button1.OnClientClick= string.Format("SubmitButton('{0}');return false;",HiddenButton.ClientID);

What row index has a template checkbox in a datagrid?

I have a datagrid and there is a checkbox which is template in each row.
Suppose I am in CheckedChanged event of one of the checkboxes. Is there any way I can tell in which row of the datagrid that check box is in?
You can through the Parent property, though you have to do something like chk.Parent.Parent and so on. I don't know how many parent references up the current row is...
HTH.
try something like this:
<script language="javascript" type="text/javascript">
function rowno(rowindex) {
var gridViewCtlId = document.getElementById("<%=GridView2.ClientID %>").rows[rowindex].cells[1].innerText;
alert('you clicked on ' + gridViewCtlId);
}
</script>
<asp:GridView ID="GridView2" runat="server" OnRowDataBound="GridView1_RowDataBound1" PageSize="5">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<%--<asp:Button ID="Button1" runat="server" Text="Button" />--%>
<asp:CheckBox ID="CheckBox1" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
in .cs
protected void GridView1_RowDataBound1(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
CheckBox delete = (CheckBox)e.Row.Cells[0].Controls[1];
delete.Attributes.Add("onclick", "javascript:rowno(" + count + ")");
count++;
}
}
Ok I found a neat solution :) In the checkedChanged event I just wrote the following:
((GridViewRow)((Control)sender).Parent.Parent).DataItemIndex;

Dynamically adding controls in ASP.NET Repeater

I find my self having a repeater control which is being databound to an xml document. My client is now requesting that the Textbox's which are being repeater can be either a Textbox or a Checkbox.
I cannot seem to find an easyway to essentially do the following:
if ((System.Xml.XmlNode)e.Item.DataItem.Attributes["type"] == "text")
<asp:TextBox runat="server" ID="txtField" Text='<%#((System.Xml.XmlNode)Container.DataItem).InnerText %>' CssClass="std"></asp:TextBox>
else
<asp:CheckBox runat="server" ID="txtField" Text='<%#((System.Xml.XmlNode)Container.DataItem).InnerText %>' CssClass="std"></asp:TextBox>
Is there a nice way I can extend my current implementaion without have to rewrite the logic. If I could inject the control via "OnItemDataBound" that would also be fine. But I cannot seem to make it work
In your repeater, drop a Panel, then create an event handler for the repeater's data binding event and programmatically create the TextBox or CheckBox and add it as a child control of the Panel. You should be able to get the DataItem from the event args to get information like your "type" attribute or values to feed your Text properties or css information, etc.
I would go with mspmsp's sugestion. Here is a quick and dirty code as an example of it:
Place this in your aspx:
<asp:Repeater ID="myRepeater" runat="server" OnItemCreated="myRepeater_ItemCreated">
<ItemTemplate>
<asp:PlaceHolder ID="myPlaceHolder1" runat="server"></asp:PlaceHolder>
<br />
</ItemTemplate>
</asp:Repeater>
And this in your codebehind:
dim plh as placeholder
dim uc as usercontrol
protected sub myRepeater_ItemCreated(object sender, RepeaterItemEventArgs e)
if TypeOf e Is ListItemType.Item Or TypeOf e Is ListItemType.AlternatingItem Then
plh = ctype(e.item.findcontrol("myPlaceHolder1"), Placeholder)
uc = Page.LoadControl("~/usercontrols/myUserControl.ascx")
plh.controls.add(uc)
end if
end sub
What about something similar to this in your markup in each the textbox and checkbox controls?
Visible=<%= Eval("type").tostring() == "text") %>
If there is needed to add controls based on data then there can be used this approach:
<asp:Repeater ID="ItemsRepeater" runat="server" OnItemDataBound="ItemRepeater_ItemDataBound">
<itemtemplate>
<div>
<asp:PlaceHolder ID="ItemControlPlaceholder" runat="server"></asp:PlaceHolder>
</div>
</itemtemplate>
</asp:Repeater>
protected void ItemRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
var placeholder = e.Item.FindControl("ItemControlPlaceholder") as PlaceHolder;
var col = (ItemData)e.Item.DataItem;
placeholder.Controls.Add(new HiddenField { Value = col.Name });
placeholder.Controls.Add(CreateControl(col));
}

Resources