I have been struggling with this for a while now.
I want to dynamically create data columns using the entity framework.
var query2 = (from c in dbc.FridayTimeSlots
where c.RoundType == "Back 9"
select c);
grvF2.Columns.Clear();
grvF2.DataSource = query2.ToList();
grvF2.Columns.Add(new BoundField { DataField = "TeeTime", HeaderText = "Tee-Off Time" });
grvF2.Columns.Add(new CommandField { HeaderText = "Select", SelectText = "Select Time", ButtonType = ButtonType.Link, ShowSelectButton = true });
grvF2.DataKeyNames = new string[] { "TimeID" };
grvF2.DataBind();
My problem, I want to only display the command field when the data field TeeTime = "something" and when TeeTime = "somethinig else" I don't want the commandfield there.
If tried just about everything but I can't get the solution.
Any help would be greatly appreciated.
In GridView's RowDataBound you can find the LinkButton and make Visible=false:
protected void grvF2_RowDataBound(object sender, GridViewRowEventArgs e)
{
GridViewRow gvr = e.Row as GridViewRow;
if (gvr != null && gvr.RowType == DataControlRowType.DataRow)
{
LinkButton lb = gvr.Cells[1].Controls[0] as LinkButton;
if (lb != null && gvr.Cells[0].Text.ToLower() != "something")
{
lb.Visible = false;
}
}
}
Assuming that you have this markup for the GridView:
<asp:GridView ID="grvF2" runat="server"
AutoGenerateColumns="false" OnDataBound="grvF2_DataBound"
OnRowDataBound="grvF2_RowDataBound" >
</asp:GridView>
And the output may look like:
Related
I am creating dynamic Template Fields for my gridview:
<asp:GridView ID="grdData" runat="server" DataKeyNames = "ID" AutoGenerateColumns="false" OnRowDataBound="grdData_RowDataBound">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:CheckBox ID="chkAll" AutoPostBack="true" OnCheckedChanged="OnCheckedChanged" runat="server" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="editbtn" AutoPostBack="true" OnCheckedChanged="OnCheckedChanged" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
the code to add templateField is below:
private void BindGridView(DataTable dtData)
{
foreach (DataColumn item in dtData.Columns)
{
TemplateField tfield = new TemplateField();
tfield.HeaderText = item.ToString();
grdData.Columns.Add(tfield);
}
grdData.DataSource = dtData;
ViewState["dtDataTable"] = dtData;
grdData.DataBind();
}
and in row databound I am adding textbox and label to the templatefield:
protected void grdData_RowDataBound(object sender, GridViewRowEventArgs e)
{
DataTable dtData = (DataTable)ViewState["dtDataTable"];
if (e.Row.RowType == DataControlRowType.DataRow)
{
int i = 1;
foreach (DataColumn item in dtData.Columns )
{
TextBox txtBox = new TextBox();
txtBox.ID = "txt"+item.ToString();
txtBox.Text = (e.Row.DataItem as DataRowView).Row[item.ToString()].ToString();
txtBox.Visible = false;
e.Row.Cells[i].Controls.Add(txtBox);
Label lblBox = new Label();
lblBox.ID = "lbl" + item.ToString();
lblBox.Text = (e.Row.DataItem as DataRowView).Row[item.ToString()].ToString();
e.Row.Cells[i].Controls.Add(lblBox);
i++;
}
}
}
Everything is working good so far,The grid is getting created and the values are getting populated ,but when i am calling below method and try to access the gridview control ,its throwing object reference error:
protected void OnCheckedChanged(object sender, EventArgs e)
{
bool isUpdateVisible = false;
CheckBox chk = (sender as CheckBox);
if (chk.ID == "chkAll")
{
foreach (GridViewRow row in grdData.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
row.Cells[0].Controls.OfType<CheckBox>().FirstOrDefault().Checked = chk.Checked;
}
}
}
CheckBox chkAll = (grdData.HeaderRow.FindControl("chkAll") as CheckBox);
chkAll.Checked = true;
foreach (GridViewRow row in grdData.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
bool isChecked = row.Cells[0].Controls.OfType<CheckBox>().FirstOrDefault().Checked;
for (int i = 1; i < row.Cells.Count; i++)
{
Label test= row.FindControl("lblName") as Label;//this is coming null
Below code lines are throwing object reference error as they are not able to find control
row.Cells[i].Controls.OfType<Label>().FirstOrDefault().Visible = !isChecked;//this line throwing object reference error
if (row.Cells[i].Controls.OfType<TextBox>().ToList().Count > 0)
{
row.Cells[i].Controls.OfType<TextBox>().FirstOrDefault().Visible = isChecked;
}
if (row.Cells[i].Controls.OfType<DropDownList>().ToList().Count > 0)
{
row.Cells[i].Controls.OfType<DropDownList>().FirstOrDefault().Visible = isChecked;
}
if (isChecked && !isUpdateVisible)
{
isUpdateVisible = true;
}
if (!isChecked)
{
chkAll.Checked = false;
}
}
}
}
btnUpdate.Visible = isUpdateVisible;
}
Edit:
I tried reinistialising the controls in preinit event but still no luck:
protected void Page_PreInit(object sender, EventArgs e)
{
if (ViewState["gridData"] != null)
{
BindGridView((DataTable)ViewState["gridData"]);
}
}
What I am doing wrong?
I recreated the dynamic gridview Controls in OnRowCreated as this event gets called in every postback instead of onRowDataBound Event and it worked like charm.
Below is how my GridView code , since the datatable is a pivoted value so the number of columns cannot be predicted. So I am adding textbox dynamically through code.
<asp:GridView ID="gvData"
EmptyDataText="There are no data records to display."
runat="server" AutoGenerateColumns="false"
HeaderStyle-BackColor="#3AC0F2"
HeaderStyle-ForeColor="White" OnRowDataBound="gvData_RowDataBound" >
<RowStyle BorderColor="LightBlue" />
</asp:GridView>
protected void Page_Load(object sender, EventArgs e)
{
foreach (var item in columnNames)
{
TemplateField tfield = new TemplateField();
tfield.HeaderText = item;
gvData.Columns.Add(tfield);
}
gvData.DataSource = ds.Tables[0];
gvData.DataBind();}
protected void gvData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
for (int i = 3; i < columnNames.Length; i++)
{
TextboxCount++;
TextBox txtName = new TextBox();
txtName.ID = "txt" + Convert.ToString(TextboxCount);
txtName.BorderStyle = BorderStyle.None;
txtName.Text = (e.Row.DataItem as DataRowView).Row[columnNames[i]].ToString();
e.Row.Cells[i].Controls.Add(txtName); }}}
Now when user try to change value in the textbox I have to validate that they only enter integer value.
Here I am not sure what has to be done.
You can use int.TyrParse method
Example
int number;
string s = "AA";
bool IsInteger = int.TryParse(s, out number);
You could use javascript function and that to textbox from code behind like:
// Add this gvData_RowDataBound , allownumbers is a javascript function
txtName.Attributes.Add("onkeypress", "javascript:return allownumbers(event);");
Or else if you are using .NET 4.5 version then try out this:
txtName.Attributes["type"] = "number";
In my Gridview I have the following template field:
<asp:TemplateField HeaderText="Dept Code" SortExpression="DeptCode">
<ItemTemplate>
<%# Eval("DeptCode") %>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlDeptCode" runat="server"
SelectedValue='<%# Eval("DeptCode") %>'
DataSource='<%# GetAllDepartments() %>'
DataTextField="DeptCode"
DataValueField="DeptCode" />
</EditItemTemplate>
</asp:TemplateField>
This works great when I click Edit on a row it populates the DropDownList with all values and selects the correct value for that row.
However, when I try to update the row: OnRowUpdating="UpdateRow"
protected void UpdateRow(object sender, GridViewUpdateEventArgs e)
{
GridViewRow row = UserGV.Rows[e.RowIndex];
DropDownList ddl = row.FindControl("ddlDeptCode") as DropDownList;
string deptCode = ddl.SelectedValue;
}
It finds the DropDownList control but the SelectedValue is always an empty string.
I need access to the selected value to save to the database.
Any ideas as to how I can get the SelectedValue of a DropDownList in a Gridview in code behind?
Edit:
You can also populate the DropDownList and SelectedValue from the code behind:
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if ((e.Row.RowState & DataControlRowState.Edit) > 0)
{
var deptMgr = new DepartmentMgr();
List<Department> departments = deptMgr.GetAllDepartments();
DropDownList ddList = (DropDownList)e.Row.FindControl("ddlDeptCode");
ddList.DataSource = departments;
ddList.DataTextField = "DeptCode";
ddList.DataValueField = "DeptCode";
ddList.DataBind();
string userDeptCode = DataBinder.Eval(e.Row.DataItem, "DeptCode").ToString();
ddList.SelectedItem.Text = userDeptCode;
ddList.SelectedValue = userDeptCode;
}
}
}
I was using a bit of a hack to get a second header for the table title when binding the gridview:
GridViewRow row = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal);
TableCell th = new TableHeaderCell();
th.HorizontalAlign = HorizontalAlign.Center;
th.ColumnSpan = UserGV.Columns.Count;
th.BackColor = Color.SteelBlue;
th.ForeColor = Color.White;
th.Font.Bold = true;
th.Text = "Manage Users";
row.Cells.Add(th);
InnerTable.Rows.AddAt(0, row);
I don't completely understand how this was interfering with getting the SelectedValue of a DropDownList control but as soon as I commented that out it started working.
For those interested I got the second header working with this using a different approach:
In the .aspx file I added this to the Gridview:
OnRowCreated="CreateRow"
And in the code behind I added the following method:
protected void CreateRow(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
GridView gridView = (GridView)sender;
GridViewRow row = new GridViewRow(1, 0, DataControlRowType.Header, DataControlRowState.Normal);
TableCell th = new TableHeaderCell();
th.HorizontalAlign = HorizontalAlign.Center;
th.ColumnSpan = UserGV.Columns.Count;
th.ForeColor = Color.White;
th.BackColor = Color.SteelBlue;
th.Font.Bold = true;
th.Text = "Manage Users";
row.Cells.Add(th);
gridView.Controls[0].Controls.AddAt(0, row);
}
}
Everything is working correctly now.
In the edit template, set the selectedvalue from the data bindings, then you will get the correct selected value instead of a null.
SelectedValue='<%# Bind("DeptCode") %>'
I have an asp:DataGrid I need to populate, and the original developer created a weird wrapper with very little flexibility, so I have decided to switch it over to a DataTable instead. The only issue is the event that it uses to populate my grid does not like my datatables. It keeps saying that it cannot convert from a DataTable to a DataRowView, which makes sense.
I need help figureing a good way to pass the data from my DataTable into the dataGrid.
Here is the event in question
protected override void ReflectItem(DataGridItemEventArgs e)
{
if (e.Item.DataItem == null) return;
DataTable currentItem = (DataTable)e.Item.DataItem;
if (currentItem == null) return;
var labelBrokerMPID = (Label)e.Item.FindControl("labelBrokerMPID");
var labelBrokerName = (Label)e.Item.FindControl("labelBrokerName");
var labelClearingBrokerDTC = (Label)e.Item.FindControl("labelClearingBrokerDTC");
//var labelClearingBrokerName = (Label)e.Item.FindControl("labelClearingBrokerName");
var linkButtonViewBroker = (LinkButton)e.Item.FindControl("linkButtonViewBroker");
var linkButtonDeleteBroker = (LinkButton)e.Item.FindControl("linkButtonDeleteBroker");
labelBrokerMPID.Text = currentItem.Rows[0]["BrokerMPID"].ToString();
labelBrokerName.Text = currentItem.Rows[0]["BrokerName"].ToString();
labelClearingBrokerDTC.Text = currentItem.Rows[0]["ClearingBrokerDTC"].ToString();
linkButtonViewBroker.CommandArgument = currentItem.Rows[0]["RelationshipId"].ToString();
}
Obviously the Datatables don't fly. I find the grid a bit frustrating since they used labels as opposed to bound columns. Would it be easier for me to reformat the data grid with bound columns as opposed to labels? Or is there an easier way to pass in my data?
As of now I store my datatable in a session variable and bind it to the DataGrid. That is when this error arrises. Is there an easy way to convert my data from a datatable to a dataRowView?
All help, advice, or critisims are appreciated!
You are almost there. You just need to cast e.Item.DataItem to DataRowView.
<asp:DataGrid ID="DataGrid1" runat="server"
OnItemDataBound="DataGrid1_ItemDataBound"
AutoGenerateColumns="false">
<Columns>
<asp:TemplateColumn HeaderText="Broker">
<ItemTemplate>
<asp:Label ID="labelBrokerMPID" runat="server" /> -
<asp:Label ID="labelBrokerName" runat="server" />
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
public DataTable MyDataSource
{
get
{
var dt = new DataTable();
dt.Columns.Add(new DataColumn("BrokerMPID", typeof (Int32)));
dt.Columns.Add(new DataColumn("BrokerName", typeof (string)));
for (int i = 0; i < 5; i++)
{
var dr = dt.NewRow();
dr[0] = i;
dr[1] = "Name " + i;
dt.Rows.Add(dr);
}
return dt;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DataGrid1.DataSource = MyDataSource;
DataGrid1.DataBind();
}
}
protected void DataGrid1_ItemDataBound(object sender, DataGridItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
var dr = e.Item.DataItem as DataRowView;
var labelBrokerMPID = e.Item.FindControl("labelBrokerMPID") as Label;
labelBrokerMPID.Text = dr["BrokerMPID"].ToString();
var labelBrokerName = e.Item.FindControl("labelBrokerName") as Label;
labelBrokerName.Text = dr["BrokerName"].ToString();
}
}
Changed the text for the labels to
Text='<%# Bind("BrokerMPID") %>'
and commented out the bulk of the event.
I can write a code.
In this I can take a Template Column & in this I build a RadCombobox.
When it's Index changed I want to affect the below text box.
Link the selected value of the Combo box is set as Text on Below TextBox.
Combo Box & Text Box are different Controls of Different Template Column.
I can Write Control of Combo box like this :
<telerik:RadComboBox ID="cmbGID" runat="server" DataSourceID="SqlDataSource8" DataTextField="Name"
DataValueField="ID" AutoPostBack="True" OnSelectedIndexChanged="cmbGID_SelectedIndexChanged">
But I don't know the parameters of this event like this :
protected void cmbGID_SelectedIndexChanged()
{
//code...
}
Any one plz tell me that parameters & tell me is that possible to set txtValue.Text = cmbGID.SelectedValue.ToString()...???
I got the solution of this problem...
This is working by following code :
protected void cmbGrp_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
RadComboBox ddlCtrl = sender as RadComboBox;
GridEditableItem dataItem = ddlCtrl.NamingContainer as GridEditableItem;
RadComboBox cmbCtrl = dataItem.FindControl("cmbSetNo") as RadComboBox;
RadTextBox txtCtrl = dataItem.FindControl("cmbSetNo") as RadTextBox;
txtCtrl.Text = ddlctrl.SelectedValue.ToString();
string query = "QUERY";
ds.Clear();
ds = c.getDataSet(query);
cmbCtrl.DataSource = ds.Tables[0];
cmbCtrl.DataTextField = "NO";
cmbCtrl.DataValueField = "RecordID";
cmbCtrl.DataBind();
}
Something like this should work:
protected void vmbGID_SelectedIndexChanged(object sender, EventArgs e)
{
var ddlCtrl = sender as RadComboBox;
if (ddlCtrl != null)
{
var dataItem = ddlCtrl.Parent as GridDataItem;
if (dataItem != null)
{
var txtCtrl = dataItem.FindControl("txtValue") as RadTextBox;
if (txtCtrl != null)
{
txtCtrl.Text = ddlCtrl.SelectedValue;
}
}
}
}