I have two textbox and one gridview in my webform. The gridview is binded with database. But I want to add one more column on runtime which will be the textbox input from the webform. Because the scenario is like: I am maintaining two formula to calculate some percentage using the two textbox and the client wants to see this calculation for each row in the gridview.
But I cannot do this.
Is there anyone who can help me on this please? May be some suggestion.
Thanks in advance.
You could add the column in your GridView markup with a label control to display the result as follows.
Here is the markup needed, please note Visible is set to false.
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField Visible="false">
<ItemTemplate>
<asp:Label ID="label1" runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Use the RowDataBound event to find the label and calculate your result as below:
void GridView1GridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
//find the control
var label1 = e.Item.FindControl("label1") as Label;
if (label1 != null)
{
if (!string.IsNullOrEmpty(tbInput1.Text) && !string.IsNullOrEmpty(tbInput2.Text))
{
// Do the calculation and set the label
label1.Text = tbInput1.Text + tbInput2.Text;
// Make the column visible
GridView1.Columns[0].Visible = true;
}
}
}
}
Please forgive any errors, I have not tested the above.
Related
I have html text data and i want to bind this data in my gridview cell.
but my datagridview is not formet html text.
exp:
string htmltext = "<p>hi some text here</p>";
dgrow.rows[0].cell[1].value=htmltext;
In this case cell value of my gridview is contain Html tag also.
so how can I format Html Text in my grid view?
I also recently had the requirement to render HTML text in a WinForms DataGridView control.
Like you I couldnt find anything out there that fitted my needs so created my own custom DataGridViewHTMLCell class.
You can find the code and sample project here: https://github.com/OceanAirdrop/DataGridViewHTMLCell
In the mark-up (please note the Mode is PassThrough):
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Literal ID="literal1" Mode="PassThrough" runat="server"></asp:Literal>
</ItemTemplate>
</asp:TemplateField>
</Columns>
Use the RowDataBound event to find the literal and set the value:
void GridView1GridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
//find the literal
var literal1 = e.Item.FindControl("literal1") as Literal;
if (literal1 != null)
{
literal1.Text = "<p>hi some text here</p>";
}
}
}
Please forgive any errors, I have not tested the above.
I am trying to disable a specific grdview row using the code below, but it isn't disabling that row. I am 100% sure there is a value called "Total Expenses" in the column that is bound to the gridview. What is more strange is that, I removed the if condition(accountTextBox.Text == "Total Expenses") to see if all the rows get disabled but only the first row is getting disabled. Any thoughts on this?
More information: Am using gridview with template fields(ASP.NET, C#). I also ran debugger and found that the accountTextBox is showing NULL. Am puzzled!
I appreciate any thoughts you may have. Thank you
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
if (!tableCopied)
{
originalDataTable = ((System.Data.DataRowView)e.Row.DataItem).Row.Table.Copy();
ViewState["originalValuesDataTable"] = originalDataTable;
tableCopied = true;
TextBox accountTextBox = (TextBox)e.Row.FindControl("AccountTextBox");
if (accountTextBox.Text == "Total Expenses")
{
e.Row.Enabled = false;
}
}
}
I'm assuming your markup looks something like this:
<asp:TemplateField HeaderText="SomeField" SortExpression="SomeField">
<EditItemTemplate>
<asp:TextBox ID="AccountTextBox" runat="server" Text='<%# Bind("SomeField") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("SomeField") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
In which case AccountTextBox will only be available in RowDataBound when e.Row.State is in Edit mode. which may or may not be available depending what update functionality is provided in your datasource...but that's something else.
Typically you don't use a TextBox to display data but lets say trying to populate a "readonly" TextBox then all you need do is move AccountTextBox from the EditTemplate to the ItemTemplate and you should be good to go.
Using the following code-behind:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
gvTest.DataSource = new List<string>() { "test1", "test2" };
gvTest.DataBind();
}
private bool tableCopied = false;
private System.Data.DataTable originalDataTable;
protected void gvTest_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
if (!tableCopied)
{
//originalDataTable = ((System.Data.DataRowView)e.Row.DataItem).Row.Table.Copy();
//ViewState["originalValuesDataTable"] = originalDataTable;
//tableCopied = true;
TextBox accountTextBox = (TextBox)e.Row.FindControl("AccountTextBox");
if (accountTextBox.Text == "Total Expenses")
{
e.Row.Enabled = false;
}
}
}
}
And this markup:
<asp:GridView runat="server" ID="gvTest" OnRowDataBound="gvTest_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="AccountTextBox" runat="server">Total Expenses</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I am not reproducing the bug. Both rows disable for me.
The tableCopied variable could be the problem. It will be set to true on the first row and this will restrict the remaining rows to enter the if condition and actually be disabled.
First row:
//tableCopied is false
if(!tableCopied) // pass
tableCopied = true
Other rows:
//tableCopied is true
if(!tableCopied) // wont pass
Note that the GridView1_RowDataBound event occurs once for every row on the same postback and every class member is persisted during the postback.
I have a requirement where i have to update a textbox if any of the value in my grid view changes.. I have a gridview with 2 rows ..
one a template field with label and another template field with a textbox...
my Grid view looks like
name value
a (empty textbox)
b (empty textbox)
c (empty textbox)
now when the user enters a value in teh text box it should automatically update another textbox which is linked to this.
Here my questions is when someone enters a value in the textbox an event should be fired!
(I am getting the names a,b,c, from database). i dont want to have an edit link or update link because all the values to be entered are mandatory!
i tried Grid_SelectedIndexChanged1 but this not firing.. is there something i am missing or i need to change so that the evant is fired and i can update the other textbox??
I am new to ASP.NET so please help!
Thanks in advance!
If the updates are supposed to be triggered when the text changes, you should use the OnTextChanged event of the TextBox, and set AutoPostBack to true.
EDIT
To avoid duplicating efforts here, using the above approach you can find the row index using the technique that Pankaj Garg outlined in his answer:
int rowIndex = ((GridViewRow)((TextBox)sender).NamingContainer).RowIndex;
The biggest caveat to this approach is that it's not forgiving of changes in the markup. If you were to wrap the TextBox in another control that implements INamingContainer, the example above would break. For example:
<asp:TemplateField>
<asp:Panel ID="Panel1" runat="server"> <!-- becomes the naming container -->
<asp:TextBox ID="TextBox1" runat="server" onchange='valueChanged(<%# Container.ItemIndex %>);' />
</asp:Panel>
</asp:TemplateField>
That being said, you would want to notate your markup accordingly so other developers know to be careful when making changes.
EDIT
As an alternative, you could also trigger the postback in JavaScript using the onchange event of the TextBox:
<script type="text/javascript">
valueChanged = function(rowIndex){
__doPostBack("<%= GridView1.ClientID %>", rowIndex);
}
</script>
<asp:GridView ID="GridView1" runat="server" DataKeyNames="ID" ...>
<Columns>
<asp:TemplateField>
<asp:TextBox ID="TextBox1" runat="server" onchange='valueChanged(<%# Container.ItemIndex %>);' />
</asp:TemplateField>
</Columns>
</asp:GridView>
In the code-behind, override the RaisePostBackEvent method, and put your update logic there:
protected override void RaisePostBackEvent(IPostBackEventHandler source, string eventArgument)
{
base.RaisePostBackEvent(source, eventArgument);
if (source == GridView1)
{
int rowIndex = int.Parse(eventArgument);
TextBox txt = GridView1.Rows[rowIndex].FindControl("TextBox1") as TextBox;
if (txt != null)
{
var id = (int)GridView1.DataKeys[rowIndex]["ID"];
var text = txt.Text.Trim();
//update the database
}
}
}
You can check the Current Row Index like below...
((GridViewRow)((TextBox)sender).NamingContainer).RowIndex
Create a handler for OnTextChanged event and set the AutoPostBack Property True.
protected void TextBox_TextChanged(object sender, EventArgs e)
{
int CurrentGridIndex = ((GridViewRow)((TextBox)sender).NamingContainer).RowIndex
}
I want to make the gridview.columns[0] as hyperlink. I tried so many work around mentioned in different sites. I am binding a list<> to the grid. and I need to make the first column as hyperlink and upon clicking that link, it should be redirected to a page with the corresponding item.
Which event I need to use and how can I pass that value from the list?
void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var firstCell = e.Row.Cells[0];
firstCell.Controls.Clear();
firstCell.Controls.Add(new HyperLink { NavigateUrl = firstCell.Text, Text = firstCell.Text });
}
}
Be warned that if you bind data to grid only first time page loaded then your changes will disappear.
You have to make that column as Template Column
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" Text="test" NavigateUrl='<%# Eval("fieldName", "show.aspx?ID={0}") %>'></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
It seems that when adding a row to an ASP.NET GridView, the Tab Index does not behave as expected (or desired). Instead of tabbing across each column in a row and then moving to the next row, the tab will move down each row in a column and then move to the next column and so on. Simply put, it will tab vertically instead of horizontally. This can be an issue for data entry applications where a user relies heavily on keyboard input.
Any solutions for this issue?
I have been screwing with this for a while and have this solution! Hope it helps other people who have the same issue.
protected void theGridView_DataBound(object sender, EventArgs e)
{
SetTabIndexes();
}
private void SetTabIndexes()
{
short currentTabIndex = 0;
inputFieldBeforeGridView.TabIndex = ++currentTabIndex;
foreach (GridViewRow gvr in theGridView.Rows)
{
DropDownList dropDown1 = (DropDownList)gvr.FindControl("dropDown1");
dropDown1.TabIndex = ++currentTabIndex;
TextBox inputField1 = (TextBox)gvr.FindControl("inputField1");
inputField1.TabIndex = ++currentTabIndex;
TextBox inputField2 = (TextBox)gvr.FindControl("inputField2");
inputField2.TabIndex = ++currentTabIndex;
TextBox inputField3 = (TextBox)gvr.FindControl("inputField3");
inputField3.TabIndex = ++currentTabIndex;
}
someLinkAfterGridView.TabIndex = ++currentTabIndex;
}
Have a look at Automatically create TabIndex in a repeater
For each control you could set the TabIndex to a property in code behind.
<asp:GridView ID="gv" runat="server">
<columns>
<asp:TemplateField HeaderText="Action" ShowHeader="False" Visible="true">
<ItemTemplate>
<asp:CheckBox ID="cbGroup" Checked="true" runat="server" TabIndex='<%# TabIndex %>' Text='<%# Eval("Title") %>' />
</ItemTemplate>
</asp:TemplateField>
</columns>
</asp:GridVeiw>
Then in code behind increment a TabIndex counter:
private int _tabIndex = 0;
public int TabIndex
{
get
{
_tabIndex++;
return _tabIndex;
}
}
You could assign the TabIndex's for all your controls inside the grid manually on the rowdatabound event. Figure out how many controls you want to tab though on a specific row and then based on the row index just formulate the tab order.