188 Points
400 Posts
Dynamic Formview with a dropdown list fails horribly.
6 hours, 21 minutes ago|LINK
I've got concept in my head that I'm trying to materialize and it's not working. Here is what needs to happen: User selects a item from a list. Based on the selection a formview is built dynamically. The formview needs to be dynamic because the query will return a dataset with null values among non-null values such as this:
4600, 1, 4, NULL, NULL, 68 ....
The "4600" is model number and everything else is a ID that corresponds to a component. The Null values means that this filed does not belong to the 4600.
Henceforth, the formview then is build such that "4600" is fed to a label. For each non-null value I need to build a dropdown list, each with a separate datascource, not the ODS stuff, but a call to BLL class. Then the non-null value is assigned to the ddl's selected value property.
Simple enough, no? So here is the code and it's failing horribly. Actually just times out in an infinite loop. The time out happens in the ddlTonerBlack_DataBinding method. Can someone tell me what I'm doing wrong? Thanks. EJM
aspx markup:
<form id="form1" runat="server">
<div>
<asp:DropDownList runat="server" ID="ddlPrinterModels" AppendDataBoundItems="True"
DataTextField="Hardware_Model" DataValueField="Hardware_Model"
width="246px" CssClass="AssetMngnt-smallFont" AutoPostBack="true" >
<asp:ListItem Value="-1" Selected="True">-- Select Printer Model --</asp:ListItem>
</asp:DropDownList>
<hr />
<asp:PlaceHolder id="DetailsViewPlaceHolder" runat="server"/>
</div>
<!-- NOT A COMPLETE QUERY -->
<asp:sqldatasource id="ODSTonerBlackByModel"
selectcommand="SELECT [Hardware_Model], [Ident_Black], [Ident_Cyan], [Ident_Yellow] FROM [cPrinters_Toners] WHERE ([Hardware_Model] = #Hardware_Model)"
connectionstring="<%$ ConnectionStrings:CISF_Asset_Management %>"
runat="server">
<SelectParameters>
<asp:ControlParameter ControlID="ddlPrinterModels" Name="Hardware_Model"
PropertyName="SelectedValue" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
</form>
Now the code file:
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadData_PrinterModels();
}
FormView printerModelFormView = new FormView();
dalConsumables_TonerBlack x = new dalConsumables_TonerBlack();
printerModelFormView.ID = "fvPrinterModel";
printerModelFormView.DataSourceID = "ODSTonerBlackByModel";
printerModelFormView.PagerSettings.Mode = PagerButtons.NextPrevious;
printerModelFormView.HeaderText = "Printer Model";
printerModelFormView.ItemTemplate = new FormViewTemplate();
DetailsViewPlaceHolder.Controls.Add(printerModelFormView);
}
protected void LoadData_PrinterModels()
{
Printer_ModelsList x = new Printer_ModelsList();
ddlPrinterModels.DataSource = x.GetPrinetr_Models();
ddlPrinterModels.DataBind();
}
protected void Page_Init(object sender, EventArgs e)
{
SqlDataSource sqlDS = new SqlDataSource();
sqlDS.ConnectionString = ConfigurationManager.ConnectionStrings["CISF_Asset_Management"].ConnectionString;
sqlDS.SelectCommand = "SELECT dbo.cCartridge_Black.Ident_Black, dbo.cCartridge_Black.Model_Black, " +
"dbo.cCartridge_Black.Desc_Black, dbo.cCartridge_Black.Qty_Black, " +
"dbo.cCartridge_Black.Black_Reorder_Limit, dbo.cCartridge_Black.Notes, " +
"dbo.cCartridge_Black.UpdatedBy, dbo.cPrinters_Toners.Hardware_Model " +
"FROM dbo.cCartridge_Black LEFT OUTER JOIN " +
"dbo.cPrinters_Toners ON dbo.cCartridge_Black.Ident_Black " +
"= dbo.cPrinters_Toners.Ident_Black";
form1.Controls.Add(sqlDS);
DropDownList ddl = new DropDownList();
ddl.ID = "ddlTonerBlack";
ddl.DataSource = sqlDS;
ddl.DataTextField = "Model_Black";
ddl.DataValueField = "Ident_Black";
form1.Controls.Add(ddl);
}
}
And the template class:
public class FormViewTemplate : System.Web.UI.ITemplate
{
void System.Web.UI.ITemplate.InstantiateIn(System.Web.UI.Control container)
{
Label lblPrinterModel = new Label();
lblPrinterModel.ID = "lblHardwareModel";
lblPrinterModel.DataBinding += new EventHandler(PrinterModelLabel_DataBinding);
container.Controls.Add(lblPrinterModel);
DropDownList ddlTonerBlack = new DropDownList();
ddlTonerBlack.ID = "ddlTonerBlack";
ddlTonerBlack.DataBinding +=new EventHandler(ddlTonerBlack_DataBinding);
container.Controls.Add(ddlTonerBlack);
}
private void PrinterModelLabel_DataBinding(Object sender, EventArgs e)
{
Label lblPrinterModel = (Label)sender;
FormView formViewContainer = (FormView)lblPrinterModel.NamingContainer;
DataRowView rowView = (DataRowView)formViewContainer.DataItem;
lblPrinterModel.Text = rowView["Hardware_Model"].ToString();
}
private void ddlTonerBlack_DataBinding(Object sender, EventArgs e)
{
DropDownList ddlTonerBlack = (DropDownList)sender;
FormView formViewContainer = (FormView)ddlTonerBlack.NamingContainer;
DataRowView rowView = (DataRowView)formViewContainer.DataItem;
dalConsumables_TonerBlack x = new dalConsumables_TonerBlack();
ddlTonerBlack.DataSource = x.GetListTonersBlack();
ddlTonerBlack.DataBind();
ddlTonerBlack.SelectedValue = rowView["Ident_Black"].ToString();
}
}
You get an infinite loop because in ddlTonerBlack_DataBinding method you call a DataBind method on the control that just fired a data bind event.
Simply you cause a databind event to fire in databind event handler of the same control and that's why you get an infinite loop.
Related
i'm building a web form that show Database's item(Tables, Rows, FK,...)
I have a CheckBoxList of Tables (chkListTable) which will show a new CheckBoxList of Rows (chkListRow) everytime I SelectedIndexChanged from chkListTable. The problem is i can show the items from chkListTable with 1 selected item. But i don't know how to show chkListRow if multiple item from chkListTable are selected.
Here are my codes:
aspx:
<div>
<asp:Label ID="Label2" runat="server" Text="Table: "></asp:Label>
<asp:CheckBoxList ID="chkListTable" runat="server"
DataTextField="name"
DataValueFeild="name"
AutoPostBack="true"
OnSelectedIndexChanged="chkListTable_SelectedIndexChanged">
</asp:CheckBoxList>
</div>
<div>
<asp:CheckBoxList ID="chkListRow" runat="server"
DataTextField="COLUMN_NAME"
DataValueField="COLUMN_NAME"
RepeatDirection="Horizontal">
</asp:CheckBoxList>
</div>
aspx.cs:
protected void chkListTable_SelectedIndexChanged(object sender, EventArgs e)
{
tableName.Clear();
foreach (ListItem item in chkListTable.Items)
{
if(item.Selected)
{
tableName.Add(item.Text.Trim());
}
}
for(int i = 0; i < tableName.Count; i++)
{
String query = "USE " + dbname +
" SELECT * FROM information_schema.columns" +
" WHERE table_name = '" + tableName[i] + "'" +
" AND COLUMN_NAME != 'rowguid'";
chkListRow.DataSource = Program.ExecSqlDataReader(query);
chkListRow.DataBind();
Program.conn.Close();
}
}
Program.cs:
public static bool Connect()
{
if (Program.conn != null && Program.conn.State == ConnectionState.Open)
Program.conn.Close();
try
{
Program.conn.ConnectionString = Program.constr;
Program.conn.Open();
return true;
}
catch (Exception e)
{
return false;
}
}
public static SqlDataReader ExecSqlDataReader(String query)
{
SqlDataReader myreader;
SqlCommand sqlcmd = new SqlCommand(query, Program.conn);
sqlcmd.CommandType = CommandType.Text;
if (Program.conn.State == ConnectionState.Closed) Program.conn.Open();
try
{
myreader = sqlcmd.ExecuteReader();
return myreader;
myreader.Close();
}
catch (SqlException ex)
{
Program.conn.Close();
return null;
}
}
I want my display to be like this:
[x]Table1 [x]Table2 [ ]Table3
[ ]Row1(Table1) [ ]Row2(Table1) [ ]Row3(Table1)
[ ]Row1(Table2) [ ]Row2(Table2)
Ok, this is a rather cute little problem.
So, if we select 1 table, then we need to have one "child" or so called ONE check box list.
but, if we select 2 tables, (or 5), then we need 2 (or 5) child check box lists.
In other words, we would not use the same check box list (child), or try to "mangle" that "N" number of check box lists we need.
So, this "child" sets (one for each checked table) is NOT known ahead of time.
So, we have "repeating" set of those child check box lists, right?
So, we can (and should) then use a "repeater". All a repeater does is "repeat" the whatever we want, and we "feed" the repeater the main list of tables.
So, our markup will now look like this:
<style>
.rBut input {margin-right: 5px; }
.rBut label {margin-right: 15px; }
</style>
<asp:Label ID="Label2" runat="server" Text="Table: "></asp:Label>
<div class="rBut">
<asp:CheckBoxList ID="chkListTable" runat="server"
DataTextField="TABLE_NAME"
DataValueFeild="TABLE_NAME"
AutoPostBack="true" RepeatDirection="Horizontal" OnSelectedIndexChanged="chkListTable_SelectedIndexChanged" >
</asp:CheckBoxList>
</div>
</div>
<div>
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
Table: <%# Eval("Table") %> -
<div class="rBut">
<asp:CheckBoxList ID="chkListRow" runat="server"
RepeatDirection="Horizontal">
</asp:CheckBoxList>
</div>
</ItemTemplate>
</asp:Repeater>
Note for the 2nd repeter, we do NOT set the Value and text columns - WE DO NOT know them yet. You did not mention which columns to display, but most of my tables always have a PK "ID" for the first column, so lets make that the value , and the display (DataTextField, the 2nd column in the given table).
So, now we build up a "list" of the first selections, (tables), and then pass that thing to the repeater, and it will repeat.
the code now looks like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadData();
}
void LoadData()
{
string strSQL = "SELECT TABLE_NAME FROM VideoGames.INFORMATION_SCHEMA.TABLES " +
"WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME";
chkListTable.DataSource = MyRst(strSQL);
chkListTable.DataBind();
}
protected void chkListTable_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable MyTables = new DataTable();
MyTables.Columns.Add("Table", typeof(string));
foreach (ListItem OneTable in chkListTable.Items)
{
if (OneTable.Selected)
{
DataRow OneRow = MyTables.NewRow();
OneRow["Table"] = OneTable.Value;
MyTables.Rows.Add(OneRow);
}
}
// ok, we have a list of tables, send that to repeater
Repeater1.DataSource = MyTables;
Repeater1.DataBind();
}
public DataTable MyRst(string strSQL)
{
var rst = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.VideoGames))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
rst.Load(cmdSQL.ExecuteReader());
}
}
return rst;
}
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item
| e.Item.ItemType == ListItemType.AlternatingItem)
{
DataRowView rItem = e.Item.DataItem as DataRowView; // get binding data row
CheckBoxList chkListRow = e.Item.FindControl("chkListRow") as CheckBoxList;
string strSQL = "SELECT * FROM " + rItem["Table"].ToString();
DataTable MyTable = MyRst(strSQL);
chkListRow.DataValueField = MyTable.Columns[0].ColumnName;
chkListRow.DataTextField = MyTable.Columns[1].ColumnName;
chkListRow.DataSource = MyRst(strSQL);
chkListRow.DataBind();
}
}
So, now we see this:
If I click one, then I see this:
But, say I click 3, then I see this:
So, note how I feed the Repeater a table (could have been sql query, but in this case, we create table in code). Pass it to repeater.
For each table, the itemdatabound triggers. Because there are multiple copies of the tables, then we need to use find control.
And if you wanted to test/get all of the checked items, then we do a for each on the Repeater items - and again use find control to get each check box control.
But note how we only have two check box lists, but the 2nd one is inside of that repeater, and is data driven.
As a result, this will work for 1, or "N" tables.
i am trying to save selected item on listbox in a single column in database as comma separated.
<td>
<%--<asp:DropDownList ID="ddlCertific" runat="server" class='form-control'></asp:DropDownList>--%>
<asp:ListBox ID="ddlCertific" runat="server" SelectionMode="Multiple">
</asp:ListBox>
</td>
binding data on page load
void BindDropdown()
{
dt = conn.GetData("SELECT CODE_DESC as datac from code ");
ddlCertific.DataSource = dt;
ddlCertific.DataTextField = "datac";
ddlCertific.DataValueField = "datac";
ddlCertific.DataBind();
}
Datasaving in database
protected void submit(object sender, EventArgs e)
{
string CERTIFIC;
CERTIFIC = ddlCertific.Text;
conn.IUD("INSERT INTO BAM(CERTIFIC) values ('"+ CERTIFIC +"')");
}
Any idea would be appreciated.
Here are the steps after some research and it is working for me
Added listbox as per question
<asp:ListBox ID="ddlCertific" runat="server" SelectionMode="Multiple" Width="229px">
<asp:ListItem Value="test1">test1</asp:ListItem>
<asp:ListItem Value="test2">test2</asp:ListItem>
<asp:ListItem Value="test3">test3</asp:ListItem>
<asp:ListItem Value="test4">test4</asp:ListItem>
</asp:ListBox>
Added a hidden field - Tricky part
<asp:HiddenField runat="server" ID="HiddenField1" ClientIDMode="Static" OnValueChanged="Date_ValueChanged" />
Javascript - This will add the selected items in the listbox using a ',' and do a post back since we need value at server
<script type="text/javascript">
function getSelectedOptions(sel) {
var opts = [], opt;
var a = [];
// loop through options in select list
for (var i=0, len=sel.options.length; i<len; i++) {
opt = sel.options[i];
// check if selected
if ( opt.selected ) {
// add to array of option elements to return from this function
opts.push(opt);
a.push(opt.value + ', ');
}
}
document.getElementById('HiddenField1').value = a.toString();
// return array containing references to selected option elements
return opts;
}
document.getElementById('ddlCertific').onchange = function (e)
{
getSelectedOptions(this);
abc();
//__doPostBack
};
function abc() {
document.getElementById('HiddenField1').value;
__doPostBack('HiddenField1');
}
</script>
Add client postback reference on server side and hiddenfield change event.
protected void Page_Load(object sender, EventArgs e)
{
string val = ClientScript.GetPostBackEventReference(this,"");
}
protected void Date_ValueChanged(object sender, EventArgs e)
{
string value = HiddenField1.Value;
//do your db stuffs
}
I am attempting to check all/specific checkboxes within a checkboxlist on pageload.
Currently there are no errors however even with Selected=true specified in the code behind, the checkboxes are displaying 'unticked'.
Here is my Code behind: (note: it is located within the Protected Void Page_Load and within if (!IsPostBack)
SqlConnection aircraftCheckConn = new SqlConnection(ConfigurationManager.ConnectionStrings["CamoDatabaseString"].ToString());
SqlCommand aircraftCheckCommand = new SqlCommand("SELECT [Type] FROM [AircraftType]");
aircraftCheckCommand.Connection = aircraftCheckConn;
aircraftCheckConn.Open();
SqlDataAdapter aircraftCheckAdapt = new SqlDataAdapter(aircraftCheckCommand);
DataSet AircraftDS = new DataSet();
aircraftCheckAdapt.Fill(AircraftDS);
AircraftCheck.DataSource = AircraftDS;
AircraftCheck.DataTextField = "Type";
AircraftCheck.DataValueField = "Type";
aircraftCheckConn.Close();
AircraftCheck.DataBind();
foreach (ListItem li in AircraftCheck.Items)
{
li.Selected = true;
}
AircraftCheck.DataBind();
Here is my front-end
<asp:CheckBoxList ID="AircraftCheck" runat="server" DataTextField="Type" DataValueField="Type" CellSpacing="10" RepeatColumns="6" RepeatDirection="Horizontal" >
</asp:CheckBoxList>
Thanks
Based from page life cycle, the Page_Load event called before binding of CheckBoxList items occur. You can replicate same code from Page_Load event in CheckBoxList's DataBound event method and put OnDataBound handler on CheckBoxList markup to corresponding method:
ASPX Markup
<asp:CheckBoxList ID="AircraftCheck" runat="server" DataTextField="Type" DataValueField="Type" CellSpacing="10" RepeatColumns="6" RepeatDirection="Horizontal"
OnDataBound="AircraftCheck_DataBound">
</asp:CheckBoxList>
Code Behind
protected void AircraftCheck_DataBound(object sender, EventArgs e)
{
// SqlConnection binding stuff here, omitted for brevity
AircraftCheck.DataBind();
foreach (ListItem li in AircraftCheck.Items)
{
li.Selected = true;
}
}
Similar issue:
How to check all checkboxes in a checkboxlist when page first loads?
My problem's probably trivial, but I can't remind myself how to do that. I have 2 dropdown lists:
<span>
<asp:DropDownList ID="DDLEditWydzial" runat="server" DataSourceID="SqlListaWydzialow"
AutoPostBack="true" DataTextField="NazwaWydzialu" DataValueField="ident"
OnSelectedIndexChanged="OnWydzialChanged" EnableViewState="true">
</asp:DropDownList>
</span>
<span>
<span style="font-size: 8pt; font-family: Arial CE">
<asp:DropDownList ID="DDLEditSale" runat="server" EnableViewState="true"
AutoPostBack="true">
</asp:DropDownList>
</span>
</span>
First one is filled with via SqlDataSource, second is filled depending on choice in previous. This is done by an event handler:
protected void OnWydzialChanged(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["sworConnectionString"].ConnectionString);
conn.Open();
using (conn)
{
SqlCommand command = new SqlCommand("SELECT '-- wybierz salÄ™ --' as numer, -1 as ident UNION " +
"SELECT 'Sala ' + s.numer as numer, s.ident FROM sala s, sala_wydzial sw where s.czyus=0 and sw.id_wydzial="
+ DDLEditWydzial.SelectedValue + " and sw.id_sala = s.ident", conn);
SqlDataReader salaReader = command.ExecuteReader();
DDLEditSale.AppendDataBoundItems = true;
DDLEditSale.DataSource = salaReader;
DDLEditSale.DataTextField = "numer";
DDLEditSale.DataValueField = "ident";
DDLEditSale.DataBind();
conn.Close();
conn.Dispose();
}
}
Then, when I chose value from 2nd list, comes postback and after a refresh list contains with data, but nothing in 2nd DDL is selected. I've checked Page_Load and DDLEditSale is empty then.
Any ideas?:)
EDIT: OnInit and InitializeComponent code (it's generated by ZedGraph):
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.ZedGraphWeb1.RenderGraph += new ZedGraph.Web.ZedGraphWebControlEventHandler(this.OnRenderGraph);
}
I've changed SqlDataSources to ObjectDataSources and it seems to work, just need to keep id of wydzial in Session. I'll paste code when I have a little time:)
I have a follow dropdown list in my aspx page:
<asp:DropDownList ID="OrderPeriodStatus" runat="server" AutoPostBack="true"
CssClass="ddlb" Width="100px" Height="30px" DataSourceID="SqlDataSource5"
DataTextField="OrderPeriod" DataValueField="OrderPeriodID" onselectedindexchanged="OrderPeriodStatus_SelectedIndexChanged">
</asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource5" runat="server" ConnectionString="<%$ ConnectionStrings:ProdDB %> # blah blah query
</asp:SqlDataSource>
I tried to access the value of selected value in C# by following code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ProcessEligibleScenarios();
LoadOptions();
ddlbPeriod.DataBind();
GridView1.DataBind();
gvActiveLogs.DataBind();
}
}
protected void OrderPeriodStatus_SelectedIndexChanged(object sender, EventArgs e)
{
if (OrderPeriodStatus.SelectedValue != null)
{
SqlConnection myConn = default(SqlConnection);
SqlCommand myComm = default(SqlCommand);
myConn = new SqlConnection(ConfigurationManager.ConnectionStrings["ProdDB"].ConnectionString);
myConn.Open();
myComm = new SqlCommand("SELECT OrderPeriodDate, OrderPeriodStatus, Notes FROM OrderPeriod WHERE OrderPeriod ='" + OrderPeriodStatus.SelectedValue + "'");
try
{
myComm.Connection = myConn;
SqlDataReader Dr = myComm.ExecuteReader();
while (Dr.Read())
{
System.Diagnostics.Debug.Write("While reading the data");
TextBox1.Text = Dr["OrderPeriodDate"].ToString();
TextBox2.Text = Dr["OrderPeriodStatus"].ToString();
NotesArea.Value = (string)Dr["Notes"];
System.Diagnostics.Debug.WriteLine(OrderPeriodStatus.SelectedValue);
}
Dr.Close();
myConn.Close();
}
catch (SqlException sqx)
{
}
GridView1.DataBind();
}
else { }
}
But when i print the value. It shows the selected Index not the value. Why?
You have mismatch error on sqdatasource, replace with SqlDataSource4
DataSourceID="SqlDataSource5" <---
<asp:SqlDataSource ID="SqlDataSource4" runat="server" ConnectionString="<%$ ConnectionStrings:ProdDB %> # blah blah query
</asp:SqlDataSource>
You can try get the value from Request.Form object and to get the text use ddl.Items.FindByValue method
var value = Request.Form[DropDownListnew.UniqeID];
var text = DropDownListnew.Items.FindByValue(value);
If you set AutoPostback property on the dropdownlist to true, and ViewStateMode to inherit, you should get value you selected. I tried it on my side, and it worked. Since you already have SqlDataSource, and the DataSourceId of the dropdownlist is set to the SqlDataSource, it should be populated automatically.
---edit
Sorry, I think I might have misread your question. If you instead use
DropDownListnew.SelectedItem.Text
you should get the text value you want.
-- another edit:
#Amit, you will get index from SelectedValue, because in your dropdownlist code, you have set
DataValueField="OrderPeriodID"
which is basically your primary key or index. To get the text value instead of index you have to use
SelectedItem.Text
Also in your query:
myComm = new SqlCommand("SELECT OrderPeriodDate, OrderPeriodStatus, Notes FROM OrderPeriod WHERE OrderPeriod ='" + OrderPeriodStatus.SelectedValue + "'");
I think you should be using
WHERE OrderPeriodID ='" + OrderPeriodStatus.SelectedValue + "'");
You are missing the ID bit after OrderPeriod.