I have created a web page that displays a table. Most of the cells of the table are already filled in but some of them require user input. I would like to put drop down menus in some of these table cells such that the cell will be populated with the selection from the menu and the drop down list will disappear.
I have gotten this to work in a single cell. However, when I tried to get it to work in a second cell everything broke. I have hacked around so much trying to find the problem that I am not even sure I remember how I got the first one working now. :-)
Here is the relevant code:
protected void Page_Load(object sender, EventArgs e)
{
// Create a DropDownList control.
DropDownList DropList = new DropDownList();
// Set the properties for the DropDownList control.
DropList.ID = "TrendList";
DropList.AutoPostBack = true;
// Manually register the event-handling method for the
// SelectedIndexChanged event.
DropList.SelectedIndexChanged += new EventHandler(this.Selection_Change);
// Because the DropDownList control is created dynamically each
// time the page is loaded, the data must be bound to the
// control each time the page is refreshed.
// Specify the data source and field names for the Text and
// Value properties of the items (ListItem objects) in the
// DropDownList control.
DropList.DataSource = CreateDataSource();
DropList.DataTextField = "ColorTextField";
DropList.DataValueField = "ColorValueField";
// Bind the data to the control.
DropList.DataBind();
// Set the default selected item when the page is first loaded.
if (!IsPostBack)
{
DropList.SelectedIndex = 0;
}
// Add the DropDownList control to the Controls collection of
// the PlaceHolder control.
p1.Controls.Add(DropList);
p2.Controls.Add(DropList);
}
ICollection CreateDataSource()
{
// Create a table to store data for the DropDownList control.
DataTable dt = new DataTable();
// Define the columns of the table.
dt.Columns.Add(new DataColumn("ColorTextField", typeof(String)));
dt.Columns.Add(new DataColumn("ColorValueField", typeof(String)));
// Populate the table with sample values.
dt.Rows.Add(CreateRow("GreenUp", "GreenUp", dt));
dt.Rows.Add(CreateRow("GreenFlat", "GreenFlat", dt));
dt.Rows.Add(CreateRow("GreenDown", "GreenDown", dt));
dt.Rows.Add(CreateRow("YellowUp", "YellowUp", dt));
dt.Rows.Add(CreateRow("YellowFlat", "YellowFlat", dt));
dt.Rows.Add(CreateRow("YellowDown", "YellowDown", dt));
dt.Rows.Add(CreateRow("RedUp", "RedUp", dt));
dt.Rows.Add(CreateRow("RedFlat", "RedFlat", dt));
dt.Rows.Add(CreateRow("RedDown", "RedDown", dt));
dt.Rows.Add(CreateRow("ClearUp", "ClearUp", dt));
dt.Rows.Add(CreateRow("ClearFlat", "ClearFlat", dt));
dt.Rows.Add(CreateRow("ClearDown", "ClearDown", dt));
// Create a DataView from the DataTable to act as the data source
// for the DropDownList control.
DataView dv = new DataView(dt);
return dv;
}
DataRow CreateRow(String Text, String Value, DataTable dt)
{
// Create a DataRow using the DataTable defined in the
// CreateDataSource method.
DataRow dr = dt.NewRow();
// This DataRow contains the ColorTextField and ColorValueField
// fields, as defined in the CreateDataSource method. Set the
// fields with the appropriate value. Remember that column 0
// is defined as ColorTextField, and column 1 is defined as
// ColorValueField.
dr[0] = Text;
dr[1] = Value;
return dr;
}
void Selection_Change(Object sender, EventArgs e)
{
// Retrieve the DropDownList control from the Controls
// collection of the PlaceHolder control.
DropDownList DropList1 = (DropDownList)p1.FindControl("TrendList");
DropDownList DropList2 = (DropDownList)p2.FindControl("TrendList");
switch (sender.ToString())
{
case "p1":
s1.InnerHtml = DropList1.SelectedItem.Value;
break;
case "p2":
s2.InnerHtml = DropList2.SelectedItem.Value;
break;
}
}
And here is the relevant snippet from the table:
<td><span id="s1" runat="server"><asp:PlaceHolder ID="p1" runat="server"></asp:PlaceHolder></span>
<td><span id="s2" runat="server"><asp:PlaceHolder ID="p2" runat="server"></asp:PlaceHolder></span>
Now I realize that the switch control is all wrong since sender does not represent the id of the caller. But I need some way to distinguish which drop down menu is the caller so I know which HTML to replace. Also, I can only get one drop down menu to display at a time.
Any advice is appreciated.
Regards.
This code solved the problem:
public void EditTable()
{
ICollection trends = CreateDataSource();
for (int x = 1; x <= 27; x++)
{
DropDownList ddl = new DropDownList();
string index = x.ToString();
ddl.ID = "TrendList" + index;
ddl.AutoPostBack = true;
ddl.SelectedIndexChanged += new EventHandler(this.Selection_Change);
ddl.DataSource = trends;
ddl.DataTextField = "TrendTextField";
ddl.DataValueField = "TrendValueField";
ddl.DataBind();
if (!IsPostBack)
{
ddl.SelectedIndex = 0;
}
HtmlGenericControl span = (HtmlGenericControl)form1.FindControl("s" + index);
PlaceHolder placeHolder = (PlaceHolder)span.FindControl("p" + index);
if (placeHolder != null)
{
placeHolder.Controls.Add(ddl);
}
}
}
Related
I have a datatable with values and I need to assign them as default values to gridview dropdown list on button click event. I have tried writing the below code and it retains only the last row values. How can I retain all the rows?
Am I missing to add rows to the GridView?
For example: DataTable now has three rows and in GridView only the third row has the default values from DataTable and the first rows are empty.
DataTable dtValues = dtSource;
if (dtValues.Rows.Count > 0)
{
for (int i = 1; i <= dtValues.Rows.Count; i++)
{
RadComboBox ID = (RadComboBox)gvGrid.Rows[i].Cells[1].FindControl("radID");
RadComboBox Names = (RadComboBox)gvGrid.Rows[i].Cells[2].FindControl("radName");
ID.SelectedValue = dtValues.Rows[i]["ID"].ToString();
Names.SelectedValue = dtValues.Rows[i]["Name"].ToString();
}
}
Can anyone please correct me if I'm doing something wrong?
You should need to use RowDataBound event of GridView as like below and populate it from DataTable as DataSource:
protected void gvGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
// check if row is not in edit mode
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataTable dtValues = dtSource;
// get dropdownlist from gridview
var ddl = e.Row.FindControl("YourDropDown") as DropDownList;
if (ddl != null)
{
ddl.DataSource = dtValues;
ddl.DataTextField = "Name"; // add text to dropdownlist
ddl.DataValueField = "ID"; // add value to dropdownlist
ddl.DataBind();
// add default selected value
ddl.Items.Insert(0, new ListItem("----- Select a Value -----", "0"));
}
}
}
Note: Don't forget to add OnRowDataBound event gvGrid_RowDataBound to your GridView.
I have a Windows Form with a DataGridView and a ComboBox. When a user clicks a row in the DGV, I want the ComboBox text to display the value in the row whether the value exists in the ComboBox or not. However, I also want users to be able to select items in the ComboBox without the ability to enter custom text.
Changing the DropDownStyle to DropDownList will not work because then I will not be able to programatically enter values that don't exist.
One idea I had was to change the style to DropDownList and temporarily add custom items and then remove them when they are no longer selected in the DGV, but I was hoping for a more elegant solution. Any help would be appreciated.
You can use the DataError event to your advantage here and add the missing item to the collection by casting the cell to a DataGridViewComboBoxCell and add the missing item to its collection:
public Form1() {
InitializeComponent();
DataTable dt = new DataTable();
dt.Columns.Add("C1");
DataRow dr1 = dt.NewRow();
dr1[0] = "ccc";
dt.Rows.Add(dr1);
DataRow dr2 = dt.NewRow();
dr2[0] = "xxx";
dt.Rows.Add(dr2);
dgv.AutoGenerateColumns = false;
var dgvCB = new DataGridViewComboBoxColumn();
dgvCB.Items.AddRange(new string[] { "aaa", "bbb", "ccc", "ddd" });
dgv.Columns.Add(dgvCB);
dgv.Columns[0].DataPropertyName = "C1";
dgv.DataError += dgv_DataError;
dgv.DataSource = dt;
}
void dgv_DataError(object sender, DataGridViewDataErrorEventArgs e) {
if (e.ColumnIndex == 0) {
string value = dt.Rows[e.RowIndex][e.ColumnIndex].ToString();
var dgvCB = (DataGridViewComboBoxCell)dgv.Rows[e.RowIndex].Cells[e.ColumnIndex];
if (!dgvCB.Items.Contains(value)) {
dgvCB.Items.Add(value);
}
}
}
What about creating the combobox_KeyPress and then add the line e.KeyChar = Nothing that will prevent any keystrokes into the box
I have a GridView, which is to be updated when User Clicks on a Button outside this GridView, a GridView Column should be updated for a particular Row.
So I m biding new Data for GridView in PostBack. But as We know PostBack is called before the OnClick Button Event. So GridView is bound at this time. But I want the update GridView column value for a particular row based on the some operations in OnClick Button Event.
So I tried to bind the GridView in OnClick Button Event also. But its not getting updated.
So my main doubt is.
Is this possible to pass value in a method which is being called in PostBack Block from the Click Event which a causing the PostBack?
private void bindTheGriView()
{
DataTable dt = new DataTable();
DataRow dr = null;
dt.Columns.Add(new DataColumn("Row Number", typeof(string)));
dt.Columns.Add(new DataColumn("POS Id", typeof(string)));
dt.Columns.Add(new DataColumn("Action", typeof(string)));
dt.Columns.Add(new DataColumn("Status", typeof(string)));
for (int index = 0; index < m_listStrPendingListOfPOS.Count; index++)
{
dr = dt.NewRow();
int iRowNo = index + 1;
dr["Row Number"] = iRowNo;
string strGridViewPOSId = m_listStrPendingListOfPOS[index];
dr["POS Id"] = strGridViewPOSId;
dr["Action"] = string.Empty;
//check for the flag. if the flag is true set status to Pending else to Associated
dr["Status"]=((Label)GridViewMultiplePOSAssociationId.Rows[index].FindControl("LabelStatusPendingPOSId")).Text;
dt.Rows.Add(dr);
}
ViewState["POSTable"] = dt;
GridViewMultiplePOSAssociationId.DataSource = dt;
GridViewMultiplePOSAssociationId.DataBind();
}
protected void btnSave_Click(object sender, EventArgs e)
{
bool statusFlag=false;
if (ViewState["RowIndexPOS"] != null)
{
int iRowIndex = Convert.ToInt32(ViewState["RowIndexPOS"]);
Label lblStatus = (Label)GridViewMultiplePOSAssociationId.Rows[iRowIndex].FindControl("LabelStatusPendingPOSId");
//Means all rows in GridView are successfully associated
if (table.Rows.Count == iResultCount)
{
lblStatus.Text = "Associated";
}
else
{
lblStatus.Text = "Pending";
}
}
//now call the binding method with the bool flag value
bindTheGriView();
}
No, I'm not using Update Panel.
Don't do it in the postback. Abstract your data bind into a method and call that method from the appropriate events.
public void BindMyData()
{
// Do data bindings on all bound controls
}
public void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
BindMyData();
}
public void myClick(object sender, EventArgs e)
{
// Update the data in the repository
BindMyData();
}
Alternatively, you could move your databinding to the Page_PreRender event to ensure that it always binds after any controls have acted.
My homework is in ASP.NET and my prof wants me to delete a row from a gridview that doesn't use a SqlDataSource. Is this possible? Because I think my prof wants to fail me just because I asked a question and he wasn't able to answer it.
Yes you can delete a row from gridview that doesn't use sqldatasource. All you have to do is delete the row from the source (whatever the source is...), that is bind to your gridview.
heres sample code for the issue:
public static DataTable dt;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
dt = new DataTable();
DataRow dr = null;
dt.Columns.Add(new DataColumn("RowNumber", typeof(string)));
dt.Columns.Add(new DataColumn("Column1", typeof(string)));
dt.Columns.Add(new DataColumn("Column2", typeof(string)));
dr = dt.NewRow();
dr["RowNumber"] = 1;
dr["Column1"] = "column1cell";
dr["Column2"] = "column2cell";
dt.Rows.Add(dr);
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
protected void LinkButton1_Click(object sender, EventArgs e)
{
if (dt.Rows.Count > 0)
{
dt.Rows.RemoveAt(0);
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
not the best code, but if your prof wants you to do, here you are.
hope this helps you...
I you Just want to delete the row find the row index and the simply call the method
datagridview.rows.removeat(rowindex);
There is a better way without having to rebind the Gridview and it forcing a call to the SqlDataSource.
Use ViewState.
When you load the Gridview, save the "data" into a ViewState variable.
ie:
//ok let's load the gridview with data as normal and display it
//'sdsClasses' is the SQL data source
gvStudents.DataSourceID = "sdsClasses";
gvStudents.DataSource = null; // Null out the source, as we have a SourceID instead
gvStudents.DataBind(); //load the gridview and display it
//save the data in a viewstate for later use
DataView dvClasses = (DataView)sdsClasses.Select(DataSourceSelectArguments.Empty);
DataTable dt = new DataTable();
if (dv != null)
{
dt = dvClasses.ToTable();
ViewState["gv"] = dt;
}
So now when ever the Gridview loads, you have the data its used in memory as a ViewState.
If you need to delete a row, do this ...
In my example I am using a search feature to look for the row I want to delete, based on a SelectValue from a dropdownlist control. You'll have to use something like that to pin-point the row you want to delete. If you wanted to delete the last row, then do a ForEach on the DataTable, row-by-row until you get to the last row and delete!
//Load the dataview that was already saved in the ViewState
DataTable dt = (DataTable)ViewState["gv"];
//find the student in the datatable, row by row
bool found = false;
bool wsAtt = false; //flag to indicate if the student is already in the roll or not saved yet (ie: sdsClasses recordset)
foreach (DataRow dr in dt.Rows)
{
//compare studentID in the datatable with the selected value of the student to delete
//check that the field has TECNQ studentIDs otherwise use the 2nd cell in the row
if (dr[0].ToString().Contains("NQ"))
found = (found || dr[0].ToString() == ddlRemoveStudents.SelectedValue);
else
{
found = (found || dr[1].ToString() == ddlRemoveStudents.SelectedValue);
wsAtt = true;
}
//he should!
if (found)
{
//remove the row to the datatable
dt.Rows.Remove(dr);
//Bind the grid view to the datatable and refresh
gvStudents.DataSource = dt;
gvStudents.DataSourceID = null; // Null out the id, we have a source
gvStudents.DataBind();
//update the viewstate with the new amount of rows
ViewState["gv"] = dt;
}
}
So you can see, using a ViewState as a replacement to the SqlDataSource, you're able to manipulate the Gridview as you wish and never call the original SqlDataSource again, except the first time to get the data.
And tell your professor he's an arrogant pig.
I am new at this. I am trying to populate a datagrid from a table source. My code is attempting to do two things.
First it populates a dataGrid with columns from a table. Then it adds a column called "SELECT" at the end of the grid. This select is CheckBox. However, when I execute this code, it adds the "SELECT" column twice.
I want to see it once. What am I doing wrong?
private void BankFlow_Load(object sender, EventArgs e)
{
initMethod();
dataTable = getBankFlowData(globalConnection);
dataGridView1.DataSource = dataTable;
}
private static DataTable getBankFlowData(OracleConnection oc)
{
DataTable dt = new System.Data.DataTable();
try
{
OracleCommand od = oc.CreateCommand();
od.CommandText = "SELECT * FROM BANK_FLOW_SOURCE";
od.CommandType = System.Data.CommandType.Text;
OracleDataAdapter adapter = new OracleDataAdapter(od);
adapter.Fill(dt);
}
catch (Exception)
{
}
return dt;
}
private static void initMethod()
{
targetSystem = ConfigurationManager.ConnectionStrings["prototype"].ConnectionString.ToString();
Console.WriteLine("Target : {0}", targetSystem);
sourceSystem = ConfigurationManager.ConnectionStrings["qlprod8"].ConnectionString.ToString();
Console.WriteLine("Source : {0}", sourceSystem);
globalConnection.ConnectionString = sourceSystem;
globalConnection.Open();
}
private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
DataGridViewCheckBoxColumn col = new DataGridViewCheckBoxColumn();
col.HeaderText = "SELECT";
col.ReadOnly = false;
col.DefaultCellStyle.BackColor = Color.Beige;
dataGridView1.Columns.Add(col);
}
Your problem is that the databindingcomplete event happens more then you think. In fact anytime some data changes it will fire.
You need to add the column outside of the databindingcomplete event.
EDIT
Actually since you are databinding, you may want to consider adding the column to your datatable. You would do this before the binding the datatable to the grid. Essentially, just create a datacolumn named select, that has the type of boolean and then add the datacolumn to the datatable.