I'm trying to upload a file onchange event of the "Fileupload" control inside gridview.
Means when ever user uploads the file, there itself I needs to save the file content in DB.
So, I had mannually called the click event of the button control on the change of fileupload control But its throwing as like exception like "Invalid postback or callback argument...."
my gridview code :
<asp:GridView runat="server" ID="grd" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="StudentID" HeaderText="Student ID" />
<asp:BoundField DataField="StudentName" HeaderText="Name" />
<asp:TemplateField HeaderText="Upload">
<ItemTemplate>
<asp:FileUpload ID="FileUpload1" runat="server" EnableViewState="true" onChange="FileUploadCall(this)" />
<asp:Button ID="btnUpload" Text="Upload" runat="server" OnClick="Upload" Style="display: none" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
My script Code :
<script type="text/javascript">
function FileUploadCall(fileUpload) {
if (fileUpload.value != '') {
var a = $('#<%=grd.ClientID %>').find('[id*="btnUpload"]');
a.click();
}
}
</script>
My Hidden Button mannual click creation in cs file :
protected void Upload(object sender, EventArgs e)
{
Button btn = sender as Button;
GridViewRow gvr = (GridViewRow)btn.Parent.Parent;
FileUpload lbleno = (FileUpload)gvr.FindControl("FileUpload1");
lbleno.SaveAs(Server.MapPath("~/Uploads/" + Path.GetFileName(lbleno.FileName)));
//lblMessage.Visible = true;
}
Your jquery code that gets the button to upload may be the reason.
Since you said you are using a gridview, so there could be multiple rows each having its own fileupload and button controls. You need to get the button control associated with this row in grid view. To get the associated button, you should be using the jquery code like below, since the associated button immediately follows the fileupload control.
if (fileUpload.value != '') {
var a = $(fileUpload).next("[id*='Button1']");
a.click();
}
The easiest way is to assign the onchange event from code behind so you can get the correct button easily. So create a RowDataBound event for the GridView.
<asp:GridView ID="grd" runat="server" OnRowDataBound="grd_RowDataBound">
Then in the RowDataBound method, use FindControl to locate and cast the FileUpload and the Button. In the method you can assign the change event to trigger a PostBack of the corresponding button.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//check if the row is a datarow
if (e.Row.RowType == DataControlRowType.DataRow)
{
//use findcontrol to locate the controls in the row and cast them
Button btn = e.Row.FindControl("btnUpload") as Button;
FileUpload fu = e.Row.FindControl("FileUpload1") as FileUpload;
//assign the button postback to the change of the fileupload
fu.Attributes.Add("onchange", "__doPostBack('" + btn.UniqueID + "','')");
}
}
Your implementations is fine only change:
a.click(); => a[0].click(); //important!!
and I hope no binding is happening in the postback:
if (!IsPostBack)
{
var list = new List<Student>();
list.Add(new Student() {StudentID = 1, StudentName = "111"});
list.Add(new Student() {StudentID = 2, StudentName = "222"});
grd.DataSource = list;
grd.DataBind();
}
I've tested it works totally fine!
Related
I have an aspx page that has a gridview with 3 fields and one button "Update". When I click on the Update button I'll be redirected to another aspx page that has a form with more information about the entry in the grid view that was selected by clicking the button "Update". The form contains more fields and a button "Delete". When I click the button "Delete" I need to close the opened form and go back to the gridview and delete that entry. I'm using TemplateField to my gridview.
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField ShowHeader="False" HeaderText=" ">
<ItemTemplate>
<asp:Button ID="Btn_Update" Text="Update" runat="server" ButtonType="Button" CommandName="update" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ID" HeaderText="ID" />
<asp:BoundField DataField="FirstName" HeaderText="First Name" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" />
</Columns>
</asp:GridView>
This is the code after I click the button "Delete" in the form to close it and go back to the gridview:
protected void btn_Delete_Click(object sender, EventArgs e)
{
#region Redirect to Page
Page.ClientScript.RegisterStartupScript(this.GetType(), "RefreshParent", "<script language='javascript'>RefreshParent()</script>");
Response.Write("<script>window.close();</" + "script>");
#endregion
ClearData();
}
How can I delete the row from the gridview after clicking the button "Delete" in the form? Thank you all
Here's some sample code so you'd get the idea. It's WPF + C#, not web, but you should get the drift. The idea is the same.
Your main program:
public delegate void DeleteRow(bool doDelete);
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
int selectedRow = 0;
public DeleteRow deleteRowDelegate;
public void ReportDelete(bool delete)
{
// Delete the row here.
}
public MainWindow()
{
InitializeComponent();
deleteRowDelegate += new DeleteRow(ReportDelete);
}
private void btnOK_Click(object sender, RoutedEventArgs e)
{
// Here, get the row number to selectedRow.
SecondaryWin win = new SecondaryWin(deleteRowDelegate);
win.ShowDialog();
// At this point, if DELETE was clicked in your secondary window, code would have executed ReportDelete() method.
}
}
And this would be your secondary window:
public partial class SecondaryWin : Window
{
DeleteRow callbackDel;
public SecondaryWin(DeleteRow callback)
{
InitializeComponent();
callbackDel = callback;
}
private void btnDel_Click(object sender, RoutedEventArgs e)
{
callbackDel.Invoke(true);
// Close the window
}
}
So in your main you register the ReportDelete() method to the DeleteRow delegate, and then pass it into your secondary window. I've passed it in the constructor, but you could use a different method if you so wishes.
Then in my secondary window you could call that delegate when you click the DELETE button, and exit that window.
Back in Main(), whenever the DELETE is clicked in your secondary window it will execute the code inside your ReportDelete() method where you could delete that particular row. Use selectedRow for this purpose.
I have Parent repeater which contains another child repeater.
For simplicity let's say that the child repeater contains text box and Requiredvalidator.
Simple example of the markup:
<asp:Repeater ID="rpt1" runat="server">
<HeaderTemplate>
....
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="lbl1" runat="server" CssClass=".."></asp:Label>
<div class="..">
<asp:Repeater ID="rpt2" runat="server">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<div class="...">
<asp:TextBox ID="txt21" runat="server" CssClass="..." MaxLength="7" CssClass="ErrorMessage" ErrorMessage="*" />
<asp:RequiredFieldValidator ID="rfv21" runat="server" CssClass="ErrorMessage" ErrorMessage="*" />
</div>
</ItemTemplate>
<FooterTemplate>
</FooterTemplate>
</asp:Repeater>
</div>
</ItemTemplate>
<FooterTemplate>
</FooterTemplate>
</asp:Repeater>
I create a method like this to get the second repeater's RequiredField id:
function getId(){
var myId = document.getElementById('<%= rfv21.ClientID %>');
}
but of course it didn't work and there was an exception:
The name control-name Does Not Exist in the Current Context
So how can i do this?
I want to mention that the business need for me is that when the onchange, onkeyup, onkeydown events fires for the txt21 it will get it's equivalent rfv21 and enbale it:
I create this method which fires for onchange, onkeyup, onkeydown events changed:
function txt21_onChange(txtbox) {
var newValue = this.value;
var oldValue = this.oldvalue;
var myRfv2 = document.getElementById('<%= rfv2.ClientID %>');
if (newValue != oldValue) {
ValidatorEnable(myRfv2, true);
}
}
and i update txt21 to be:
<asp:TextBox ID="txt21" runat="server" CssClass=".." MaxLength="7" onkeyup="javascript: txt21_onChange(this);this.oldvalue = this.value;" />
but this line want work:
var myRfv2 = document.getElementById('<%= rfv2.ClientID %>');
as i explained before.
I think Item.FindControl(..) may help but how can we use it in this case?
You can bind the javascript function call from Repeater Repeater.ItemDataBound event.
Code Bahind
void R1_ItemDataBound(Object Sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
TextBox txt21 = (TextBox)e.Item.FindControl("txt21");
RequiredFieldValidator rfv21 = (RequiredFieldValidator)e.Item.FindControl("rfv21");
txt21.Attributes.Add("onclick", "txt21_onChange('" + txt21.ClientID + "','" + rfv21.ClientID + "'" )
}
}
Javascript
function txt21_onChange(txt21ID, rfv21ID)
{
txt21ID = document.getElementById(txt21ID);
rfv21ID = document.getElementById(rfv21ID);
//The above are TextBox and RequiredFieldValidator objects of row of TextBox that triggered change event.
//You can use these object
}
The problem here is that there going to be many such controls, one per each row of each child repeater. All will have slightly different generated IDs. So instead of querying them by id (impossible), you can use jQuery to quickly find them relatively to the txt that fired an event:
function txt21_onChange(txtbox) {
var rfv2 =
$(textbox) // gives you the jquery object representing the textbox
.closest("div") // the parent div
.find("id*='rfv2'"); // the element you are looking for, id contains rfv2
This answers the immediate question in this thread on how to get hold of the element. But I am not sure it will solve your bigger problem of enabling/disabling validation. You cannot easily do so with server side controls in javascript. Besides, validator is not disabled by default in your code. Although I believe all this is worth a separate question here on SO>
I have <telerik:RadGrid/>
inside this grid i have the following column contains button
<telerik:GridTemplateColumn >
<ItemTemplate>
<asp:Button ID="btnDelete" runat="server" Text="Delete"
CommandArgument='<%#Container.ItemIndex%>' OnCommand="btnDelete_Command">
protected void btnDelete_Command(object sender, CommandEventArgs e)
{
Telerik.Web.UI.GridDataItem item = gvAllDocuments.Items[int.Parse(e.CommandArgument.ToString())];
string FileName = item["documentFileName"].Text;
}
how I can add confirmation message before function btnDelete_Command executing ..
Do not use ItemIndex. It is just a row index of the grid. Instead, you want to set unique id inside DataKeyNames.
Ideally, you do not want to implement your own delete button, because telerik already has delete button which calls OnDeleteCommand automatically.
It is a prefer way of doing it for RadGrid.
<telerik:RadGrid ... OnDeleteCommand="RadGrid_DeleteCommand">
<MasterTableView DataKeyNames="xxxId" ...>
<Columns>
<telerik:GridButtonColumn
ButtonType="ImageButton"
ConfirmText="Are you sure you want to delete?"
CommandName="Delete"
ImageUrl="~/Images/Delete.png"
Text="Click to delete" UniqueName="Delete">
</telerik:GridButtonColumn>
</Columns>
...
</MasterTableView>
</telerik:RadGrid>
protected void RadGrid_DeleteCommand(object source, GridCommandEventArgs e)
{
int id = Convert.ToInt32(
e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["xxxId"]);
// Delete logic here.
}
I have two GridViews. The user can select a row from the first GridView and a list based on the GridView ID selected will display.
First Grid:
Second Grid:
Code for first GridView:
<asp:GridView style="width:75%"
ID="gvCVRT"
ShowHeaderWhenEmpty="true"
CssClass="tblResults"
runat="server"
OnSelectedIndexChanged="gridviewParent_SelectedIndexChanged"
OnRowDataBound="gvCVRT_RowDataBound"
DataKeyField="ID"
DataKeyNames="ChecklistID"
AutoGenerateColumns="false"
allowpaging="false"
AlternatingRowStyle-BackColor="#EEEEEE">
<HeaderStyle CssClass="tblResultsHeader" />
<Columns>
<asp:BoundField DataField="ChecklistID" HeaderText="ID" ></asp:BoundField>
<asp:CommandField ShowSelectButton="True" HeaderText="Select" />
<asp:BoundField DataField="ChecklistDate" HeaderText="Checklist Date" dataformatstring="{0:dd/MM/yyyy}"></asp:BoundField>
<asp:BoundField DataField="User" HeaderText="User" ></asp:BoundField>
<asp:BoundField DataField="Note" HeaderText="Note" ></asp:BoundField>
<asp:TemplateField HeaderText="Delete" ItemStyle-CssClass="tblRowDelete">
<ItemTemplate>
<asp:LinkButton ID="btnDelete"
runat="server" OnClientClick="event.stopPropagation()" OnClick="btnDeleteCVRT_Click"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code behind:
protected void gvCVRT_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
lookupCVRT work = (lookupCVRT)e.Row.DataItem;
GridView gv = sender as GridView;
string checklistid = work.ChecklistID.ToString();
e.Row.Attributes.Add("ID", "gvCVRT_" + work.ID);
LinkButton btnDelete = (LinkButton)e.Row.FindControl("btnDelete");
btnDelete.CommandArgument = checklistid;
if (work.ID != null)
{
int index = gv.Columns.HeaderIndex("Select");
if (index > -1)
{
e.Row.Cells[index].Attributes.Add("class", "gvCVRTRow");
e.Row.Cells[index].ToolTip = "Click here to Edit Checklist";
e.Row.Cells[index].Attributes.Add("style", "color:blue;cursor:pointer;cursor:hand");
}
}
}
}
Code for gridviewParent_SelectedIndexChanged:
protected void gridviewParent_SelectedIndexChanged(object sender, EventArgs e)
{
List<lookupCVRT> workDetails = lookupCVRT.GetChecklistItemsByChecklistID(Company.Current.CompanyID, ParentID.ToString(), gvCVRT.SelectedDataKey.Value.ToString());
gvCVRTDetails.DataSource = workDetails;
gvCVRTDetails.DataBind();
FireJavascriptCallback("setArgAndPostBack ();");
}
Javascript:
$(".gvCVRTRow").off();
$(".gvCVRTRow").click(function (e) {
ShowAddEditCVRT(this, "Edit");
});
function ShowAddEditCVRT(sender, AddEdit) {
$("#divCVRTDetails").fadeIn(300);
}
Sorry its a lot of code but I wanted to show exactly what is happening. When I set the code to int index = gv.Columns.HeaderIndex("Select"); it goes into the javascript function ShowAddEditCVRT first, which tries to display the second grid divCVRTDetails. But I need to run the method gridviewParent_SelectedIndexChanged first because this binds the second grid with the ID selected from the first grid.
The only way I can get the second grid to bind first is to change the code to this: int index = gv.Columns.HeaderIndex("Checklist Date");.
So the user has to click on select first (to bind the grid) then click on the date cell to display the grid.
so my question is, is there anyway to run the gridviewParent_SelectedIndexChanged method before the javascript function gets called?
See the link below for more detail where I found this information.
http://www.codeproject.com/Questions/246366/run-javascript-from-side-server-in-asp-net-and-csh
You can add your javascript from the server side after you bind your gridview.
protected void Page_Load(object sender, EventArgs e) {
String script = #"<script language=""Javascript"">
$(".gvCVRTRow").off();
$(".gvCVRTRow").click(function (e) {
ShowAddEditCVRT(this, "Edit");
});
function ShowAddEditCVRT(sender, AddEdit) {
$("#divCVRTDetails").fadeIn(300);
}
</script>";
Page.RegisterClientScriptBlock("experiment", script);
gvCVRT.Attributes.Add("DataBound", "TestJScript()");
I believe this replaces your FireJavascriptCallback("setArgAndPostBack ();");
EDIT
I changed the code to better match what you provided and also where to put the code. I think it should go under page load. I also changed the gvCVRT.Attributes.Add to make it so the javascript runs when the gvCVRT is databound.
Answer to this is I called the javascript by using FireJavascriptCallback("myFunction();"); then just put the javascript code I needed into this function.
FireJavascriptCallback is a function:
protected void FireJavascriptCallback(string JSFunctionName)
{
System.Web.UI.ScriptManager.RegisterClientScriptBlock(this.Page, this.Page.GetType(), "Callback", JSFunctionName, true);
}
Good day,
I have a repeater that contain link button. The value and number of link button is generate base on data pull from database. The HTML code is something as follow:
<asp:Repeater ID="repCategories" runat="server" EnableViewState="false">
<ItemTemplate>
</ItemTemplate>
</asp:Repeater>
Here is some code that I try to do in my code behind,
for (int i = 0; i < table.Rows.Count; i++)
{
RepeaterItem itm = repCategories.Items[i];
GiftRow dr = tbl.GetRow(i);
Literal litLink2 = (Literal)itm.FindControl("litLink2");
litLink2.Text = dr.Name;
string myScript = string.Empty;
myScript = "\n<script type=\"text/javascript\" language=\"Javascript\" id=\"EventScriptBlock\">\n";
myScript += "alert('hi');";
myScript += "\n\n </script>";
Page.ClientScript.RegisterStartupScript(this.GetType(), "myKey", myScript, false);
}
By doing this, I will get alert hi when I load the page.What I want to do is, I only want it do alert hi when I click on the link button, instead of page load.
Use a LinkButton and leverage the ClientClick event instead:
<asp:Repeater ID="repCategories" runat="server" EnableViewState="false">
<ItemTemplate>
<asp:LinkButton ID="lbMyLinkButton" runat="server" />
</ItemTemplate>
</asp:Repeater>
I'd also recommend you use ItemDataBound events of repeaters where possible:
void repCategories_ItemDataBound(Object Sender, RepeaterItemEventArgs e) {
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) {
((LinkButton)e.Item.FindControl("lbMyLinkButton")).OnClientClick = "alert('hi');";
}
}
NOTES:
I wouldn't ever recommend you render javascript server-side unless absolutely necessary. I've provided an answer to fit in with the context of your question, but I would advise you have a javascript function already on your page and 'wire it up' server-side (if not bind it on the client with pure javascript)
There is also an assumption here that you're binding data to the repeater (you should be anyway), which means you also have to wire up the ItemDataBound handler: repCategories.OnItemDataBound += repCategories_ItemDataBound