FindControl recursive - error when finding my FileUpload control in GridView - c#

I have been trying the whole day to fix this, hope someone can give me an answer!
(please keep in mind I'm a beginner in this coding).
I have a database where one of the fields is an imageurl. I have to be able to update this field and thought that I could do so using a GridView with an UpdateItemTemplate.
I soon found out that you have to use the FindControl recursive method to do so - so I implemented the code and I'm now stuck with another error.
I think I know why the error appears, but have no idea how to fix it. It seems that in the tools.cs file the identifier of the control is set to be of data type String, but I have no clue what to do with a FileUpload.
Here is the error message:
cannot convert from 'System.Web.UI.WebControls.FileUpload' to 'string'
ASP.NET GridView control:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="DrinkCategoryID" DataSourceID="ObjectDataSource1">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:BoundField DataField="DrinkCategoryID" HeaderText="DrinkCategoryID"
InsertVisible="False" ReadOnly="True" SortExpression="DrinkCategoryID" />
<asp:TemplateField HeaderText="DrinksCategoryName"
SortExpression="DrinksCategoryName">
<EditItemTemplate>
<asp:FileUpload ID="FileUpload1" runat="server" />
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("DrinksCategoryName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The tool (FindControl)
public static Control FindControlRecursive(Control Root, string Id)
{
if (Root.ID == Id)
return Root;
foreach (Control Ctl in Root.Controls)
{
Control FoundCtl = FindControlRecursive(Ctl, Id);
if (FoundCtl != null)
return FoundCtl;
}
return null;
}
And code behind for the web form (click event for the save button)
protected void btnGem_Click(object sender, EventArgs e)
{
FileUpload FileUpload1 = (FileUpload)Tools.FindControlRecursive(
GridView1, FileUpload1);
//This seems to work fine
TextBox txtBox = (TextBox)Tools.FindControlRecursive(GridView1, txtBox.Text);
}

On the first line of your button handler, you're passing the control itself as the second parameter of FindControlRecursive - you need to pass in the string ID of the control you're looking for. In other words:
protected void btnGem_Click(object sender, EventArgs e)
{
FileUpload FileUpload1 = (FileUpload)Tools.FindControlRecursive(GridView1, "FileUpload1");
TextBox txtBox = (TextBox)Tools.FindControlRecursive(GridView1, txtBox.Text); //This seems to work fine
}

Related

Response.Redirect is not redirecting my page

I have a gridview that has a button in which the OnClick event calls the button's OnClick method. There is some processing code and then the redirect code. There is also an OnClientClick event that calls a javascript function.
After clicking the button, the page doesn't redirect. It only refreshes.
Here is the gridview:
<asp:GridView ID="gvLinkedOptions"
runat="server"
CssClass="table table-striped"
AutoGenerateColumns="false"
Visible="false"
Gridlines="Horizontal"
EnableViewState="false">
<Columns>
<asp:TemplateField HeaderText="Linked Number">
<ItemTemplate>
<asp:Button ID="btnLinkedNbr" CssClass="linkBtn" runat="server"
ClientIDMode="Static"
Text='<%# Eval("LinkedNbr") %>'
OnClientClick="showName(this.value)"
OnClick="btnLinkedNbr_Click" />
</ItemTemplate>
</asp:TemplateField>
//Other ItemTemplate columns
</Columns>
<EmptyDataTemplate>
No Results found
</EmptyDataTemplate>
</asp:GridView>
Here is the click method:
protected void btnLinkedNbr_Click(object sender, EventArgs e)
{
string LinkedNbr = Convert.ToString(txtLinkedNbr.Text);
DataView dv = dalLinkSearch.GetInstance().SearchByLinkedNbr(LinkedNbr);
if (DataUtil.HasValue(dv))
{
Int32 LinkID = DataUtil.GetInt32(dv[0]["LinkID"]);
if (LinkID == -1)
{
string BlockMessage = GetLookupTableItem("SystemLock", "LockMessage", "Security");
Tracking.CommonUtil.Utils.NotifyError(BlockMessage);
}
else
{
Base_DAL.RefreshWorkingEntity(LinkedNbr, "LI");
Response.Redirect("~/West/LinkedTask.aspx", false);
}
}
else
{
Tracking.CommonUtil.Utils.notifyInfo("Linked Number Not Found.");
}
}
I have tried ResolveURL() and plugged that value into the redirect method parameter with no luck.
There is an UpdatePanel on the page, but the gridview is not in it.
When debugging the click method, there is an error:
ClientDisconnectedToken 'this.Response.ClientDisconnectedToken' threw an exception of type 'System.PlatformNotSupportedException' System.Threading.CancellationToken {System.PlatformNotSupportedException}
I am not sure if that is causing the problem. It would be strange if it is because this same code, except for using a gridview, works throughout the project.
My question is why does my page refresh instead of being redirected.

Nesting Gridview inside Formview breaks insert codebehind context

I have a couple of GridViews in my FormView page and I am wanting to make an Insert row in the FooterRow of the Gridviews. Layout and everything is fine. However, as I'm building the codebehind for the Insert command, I'm running into a context problem. If I move the GridView outside of the FormView markup, the context errors clear up immediately.
GridView Markup
<asp:GridView ID="gvBFMats" runat="server" ShowFooter="True" AutoGenerateColumns="False" DataKeyNames="MaterialID" DataSourceID="BFMatsSQL" OnRowCommand="gvBFMats_RowCommand">
<Columns>
<asp:TemplateField HeaderText="Commands" ShowHeader="False">
<EditItemTemplate>
<asp:LinkButton ID="ButtonUpdate" runat="server" CausesValidation="True" CommandName="Update" Text="Update"></asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel"></asp:LinkButton>
</EditItemTemplate>
<ItemTemplate>
<asp:LinkButton ID="ButtonEdit" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit"></asp:LinkButton>
<asp:LinkButton ID="ButtonDelete" runat="server" CausesValidation="False" CommandName="Delete" Text="Delete"></asp:LinkButton>
</ItemTemplate>
<FooterTemplate>
<asp:LinkButton ID="ButtonAdd" runat="server" CommandName="Insert" Text="Add to Table" />
</FooterTemplate>
...
Insert Command Codebehind
protected void gvBFMats_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Insert" && Page.IsValid)
{
BFMatsSQL.Insert();
}
}
protected void BFMatsSQL_Inserting
(object sender, ObjectDataSourceMethodEventArgs e)
{
DropDownList ddlNewMfr =
(DropDownList)gvBFMats.FooterRow.FindControl("ddlNewMfr");
DropDownList ddlNewThickness =
(DropDownList)gvBFMats.FooterRow.FindControl("ddlNewThickness");
DropDownList ddlNewCore =
(DropDownList)gvBFMats.FooterRow.FindControl("ddlNewCore");
DropDownList ddlNewSize =
(DropDownList)gvBFMats.FooterRow.FindControl("ddlNewSize");
TextBox txtNewColor =
(TextBox)gvBFMats.FooterRow.FindControl("txtNewColor");
TextBox txtNewQty =
(TextBox)gvBFMats.FooterRow.FindControl("txtNewQty");
DropDownList ddlNewFinish =
(DropDownList)gvBFMats.FooterRow.FindControl("ddlNewFinish");
TextBox txtNewExtra =
(TextBox)gvBFMats.FooterRow.FindControl("txtNewExtra");
// Set the SQLDataSource's InsertParameters values
e.InputParameters["MatManufacturerID"] =
Convert.ToInt32(ddlNewMfr.SelectedValue);
e.InputParameters["MatThicknessID"] =
Convert.ToInt32(ddlNewThickness.SelectedValue);
e.InputParameters["MatCoreID"] =
Convert.ToInt32(ddlNewCore.SelectedValue);
e.InputParameters["MatSizeID"] =
Convert.ToInt32(ddlNewSize.SelectedValue);
e.InputParameters["MatFinishPrePostID"] =
Convert.ToInt32(ddlNewFinish.SelectedValue);
string strNewColor = null;
if (!string.IsNullOrEmpty(txtNewColor.Text))
strNewColor = txtNewColor.Text;
e.InputParameters["MatFinishColor"] = strNewColor;
int? intNewQty = null;
if (!string.IsNullOrEmpty(txtNewQty.Text))
intNewQty = Convert.ToInt32(txtNewQty.Text);
e.InputParameters["MatQty"] = intNewQty;
string strNewExtra = null;
if (!string.IsNullOrEmpty(txtNewExtra.Text))
strNewExtra = txtNewExtra.Text;
e.InputParameters["MatNumExtraSheets"] = strNewExtra;
}
Specifically, I get the red squiggly under the gvBFMats in the (Control)gvBFMats.FooterRow.FindControl("Control ID"); that says "The name 'gvBFMats' does not exist in the current context." I'm only guessing that it doesn't like the call to the GridView when it's nested inside a FormView template. Is there a way to pass this context along programatically?
You're right about it not recognizing the name gvBFMats because it's embedded in a template. Only "top-level", non-embedded controls will be treated in Code Behind as if they had been explicitly declared. Controls declared in a template will not. The compiler doesn't recognize those names.
There's a reason for this. Imagine you have a control called TextBox1 in one of the ItemTemplates for a repeating control. You bind it. Your page's control tree now has dozens of controls with the ID TextBox1. If you want to refer to TextBox1, how does it know which one you mean?
So. What can you do in your situation? Well, BFMatsSQL_Inserting and gvBFMats_RowCommand are both event handlers, so you can't change their signatures.
But, you can make use of them belonging to the same class, and use a module-level variable to hold the reference to gvBFMats. Like this:
private GridView gvBFMats;
protected void gvBFMats_RowCommand(object sender, GridViewCommandEventArgs e)
{
gvBFMats = [your form view].Row.FindControl("gvBFMats") as GridView;
if (e.CommandName == "Insert" && Page.IsValid)
{
BFMatsSQL.Insert();
}
}
Now, BFMatsSQL_Inserting will be able to refer to gvBFMats, and it should have a value.

How to get datatextfield value

I am making a web site in visual studio 2012, using asp.net, c#.
I created a grid view, which is taking data from my sql server, and created a button field which is bound to id_p, which is one of the collumns taken from a database. I am trying to get the data of the id_p for the row in which the button was clicked.
<asp:ButtonField ButtonType="Button" DataTextField="id_p"
DataTextFormatString="Stavi u košaricu" Text="Button1" />
What I need is not the selected row, only the id_p value, so how could I do that, please?
You need to handle the OnRowCommand Event on the gridview as so:
<asp:GridView ID="GridView1" runat="server" OnRowCommand="GridView_RowCommand"
And create a ItemTemplateField to display a regular <asp:button> instead of using the ButtonField column:
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btn" runat="server"
CommandName="Something" CommandArgument='<%#Eval("id_p") %>'
Text="Stavi u košaricu" />
</ItemTemplate>
</asp:TemplateField>
Now you handle the RowCommand Event:
protected void GridView_RowCommand(Object sender, GridViewCommandEventArgs e)
{
string m_id = e.CommandArgument.ToString();
if (e.CommandName == "Something")
{
//do something with m_id
}
}

Programmatically access GridView columns and manipulate

I have a GridView :
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" GridLines="None"
HorizontalAlign="Left" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1" onrowcommand="GridView1_RowCommand1">
<HeaderStyle HorizontalAlign="Left" />
<Columns>
<asp:TemplateField HeaderStyle-Width="150">
<HeaderTemplate>
<b>Downloads</b>
</HeaderTemplate>
<ItemTemplate>
<!-- <asp:HyperLink ID="hyperlinkDownload" runat="server" NavigateUrl="" >Download
MP3</asp:HyperLink> -->
<asp:LinkButton CommandName="download"
CommandArgument='<%# Eval("Name") %>' runat="server">Download MP3</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</asp:GridView>
I want to query the value of a particular field in a DB and if it's true, display the LinkButton. if false, I want the linkButton not to be displayed.
is there a way to access the GridView programmatically and make visible certain of its columns or manipulate its items ?
help.
You can do this by adding a handler to the RowDataBound event. Add an event handler along this lines of this in your code behind:
protected void myGrid_RowDataBound(Object sender, GridViewRowEventArgs e)
{
var data = e.Row.DataItem as DataRowView;
if (data != null)
{
var lbtDownload = e.Row.FindControl("lbtDownload");
lbtDownload.Visible = (bool) data.Row["HasFileForDownload"];
}
}
In your markup, attach the event handler to the grid:
<asp:GridView OnRowDataBound="myGrid_RowDataBound" ...>
You will also need to assign an id to the LinkButton, matching the one that you are search for using the FindControl() method in the event handler.
Disclaimer: I am on currently a Linux machine with no chance of testing this. Please report any bugs in the code - feel free to correct them if you have editor rights.
Yes there is.
1) You need to subscribe the RowDataBound event.
2) Give the LinkButton an ID.
3) Insert in codebehind
protected void GridView1_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton _bt = e.Row.FindControl("ID") as LinkButton;
if(_bt != null)
{
// have a look at the e.row.DataItem and try to get the value of your desired visibility property
_bt.Visible = true;
}
}
}
4) If this does not work with accessing the DataItem, start thinking about a LinqDataSource.

Get the Current Selected Row of GridView on a button Click

I want to fetch the DataKey of the Selected Row of GridView on button click.
I would Personal do it in a Template Field Like so:
<asp:TemplateField>
<ItemTemplate>
//EDIT: after a comment it is suggested that you pass the RowIndex as the command argument which would provide access to the entire row
<asp:LinkButton ID="btnCopy" runat="server"CausesValidation="False"CommandName="MyCommandButton"CommandArgument='<%# Eval("MyDataKeyOrWhateverIWanteverIWantFromTheBindingSource")%>'>
</ItemTemplate>
</asp:TemplateField>
CodeBehind
protect void MyCommandButton(Object sender,CommandArgument e)
{
int DataKeyOrPK=int32.Parse(e.CommandArgument.ToString());
}
You other option would be:
<asp:gridview id="myGrid" runat="server"
width=100% datakeynames="Myid"
autogeneratecolumns=false
onSelectedIndexChanged="MyEvent">
<asp:templatefield headertext="Choose your dream home">
<itemtemplate>
<asp:linkbutton runat="server" commandname="select" text='<%# Eval ( "Whatever" ) %>' />
</itemtemplate>
</asp:templatefield>
Note the commandname="select" above.
Data-bound controls recognize certain command names and automatically raise and handle the appropriate events for the control. The following command names are recognized:
Cancel, Delete, Edit, Insert, New, Page, Select, Sort and Update. Reference
Codebehind
private void MyEvent(Object sender, EventArgs e)
{
string id = myGrid.SelectedDataKey.Value.ToString();
}
Use the SelectedDataKey property of the GridView:
DataKey currentKey = myGridView.SelectedDataKey;

Categories