I have a DropDownList which I initialize in a function called CreateChildControls before adding it to the Controls collections. I then override the Render() method and then render the DropDownList. The web part inherits from System.Web.UI.WebControls.WebParts.WebPart.
I bind the DropDownList in my web part like this:
private void BindClientTypes()
{
DataTable dt = DB.GetAllClientTypes();
if (dt == null)
{
ltGlobalErrorMsg.Text = GlobalErrorMessage;
ltGlobalErrorMsg.Visible = true;
}
else
{
ddlClient.DataSource = dt;
ddlClient.DataValueField = "ID";
ddlClient.DataTextField = "Name";
ddlClient.DataBind();
ddlClient.Items.Insert(0, PleaseSelectItem);
}
}
If I try to set the SelectedIndex of the DropDownList after calling DataBind, I get an error which says the control cannot have multiple selected items.
That code works fine, and I can set the SelectedIndex after the data bind if I comment out this line:
ddlClient.Items.Insert(0, PleaseSelectItem);
Can anyone explain why this wouldn't work?
Thanks.
ddl.Items.Add(new ListItem("yourtext", "yourvalue"));
When you set the 'selected' property you are setting it to that ListItem's instance so if you have more ListItems that you are reusing then they will all get the same value which is probably causing the issue you are experiencing.
To illustrate the problem see this example with 2 dropdownlists:
ListItem item1 = new ListItem("1", "1");
ListItem item2 = new ListItem("2", "2");
ListItem item3 = new ListItem("3", "3");
ddlTest.Items.Add(item1);
ddlTest.Items.Add(item2);
ddlTest.Items.Add(item3);
ddlTest2.Items.Add(item1);
ddlTest2.Items.Add(item2);
ddlTest2.Items.Add(item3);
ddlTest2.SelectedValue = "2";
Setting ddlTest2's selected value actually sets ddlTest as well since they share the same items list. If you run this bother ddlTest and ddlTest2 will have the exact same selected value even though only ddlTest2 was set.
Where is PleaseSelectItem declared? If you add the same instance of a listitem to many dropdownlists you are liable to get this problem.
Related
I have BindingSource defined:
public System.Windows.Forms.BindingSource bsContractors;
this.bsContractors.DataSource = typeof(Contractor);
and then a ComboBox with a DataSource defined like so:
private System.Windows.Forms.ComboBox cmbConstructionContractors1;
this.cmbConstructionContractors1.DataBindings.Add(new System.Windows.Forms.Binding("SelectedValue", this.bsProject, "Id", true));
this.cmbContractors1.DataSource = this.bsContractors;
this.cmbContractors1.DisplayMember = "Name";
this.cmbContractors1.ValueMember = "Id";
this.cmbContractors1.SelectedIndexChanged += new System.EventHandler(this.cmbContractor1Selected);
This works fine.
I have another ComboBox defined on another Form using the same DataSource:
this.cmbContractorName2.DataBindings.Add(new System.Windows.Forms.Binding("SelectedValue", myView.bsProject, "Id", true));
this.cmbContractorName2.DataSource = projectView.bsContractors;
this.cmbContractorName2.ValueMember = "Id";
this.cmbContractorName2.DisplayMember = "Name";
this.cmbContractorName2.SelectedIndexChanged += new System.EventHandler(this.cmbContractor2Selected);
When this 2nd ComboBox is displayed, the first ComboBox, which has something selected, gets reset to the first entry, which is blank.
If I pull down on the first ComboBox, the list is still there, it just 'forgot' which one was selected.
Edit: I've discovered that when displaying the 2nd ComboBox, the EventHandler of the 1st ComboBox1 somehow gets assigned to cmbContractors2Selected instead of the original cmbContractors1Selected
Try giving it its own binding object:
this.cmbContractorName2.DataSource = new BindingSource(projectView.bsContractors, null);
This will separate the currency managers.
It is a very weird problem
when I change the value of the drop down list, a new drop down list is show. I am so confused,
To know what I am talking about, please check these images.
edit
code for bind
CallerId = Request["CallerID"];
if (String.IsNullOrWhiteSpace(CallerId)) return;
var results = ZumaDa.GetCustomerInformation(CallerId);
rowCount = results.Rows.Count;
CallerId = rowCount > 0 ? results.Rows[0][4].ToString() : CallerId;
if (rowCount > 1)
{
ListView1.Enabled = false;
GridView1.DataSource = results;
GridView1.DataBind();
}
else
{
GridView1.Enabled = false;
ListView1.DataSource = results;
ListView1.DataBind();
}
That code is in page load and NOT on !ispostback
Since you updated your question with the ListView markup, and your Page_Load code, it appears the problem of the duplicated DropDownList goes away after you wrap your databinding code in an if (!Page.IsPostBack) block.
One problem in your code is that, in your SelectedIndexChanged event, you're searching the ListView for your DropDownList and TextBox. You need to search the ListViewItem control where the SelectedIndexChanged event occurred.
To do that, you can first get the DropDownList from the "sender" parameter. Then you should find the "NamingContainer" control of the DropDownList, and search that. Like this:
var dropDown = (DropDownList)sender;
var visitID = (TextBox)dropDown.NamingContainer.FindControl("visitID");
That second line of code might need to have an additional ".NamingContainer" depending on your markup.
I think you need to bind listview in !IsPostback check means when do postback it pageload event fired and it bind dropdown with second time or if its not please share binding code
I have three drop down menus that are using a store Procedure to populate my gridview. I need the first facility DropDown to give different options in the second source type dropdown depending on what facility is selected. Some facility's need to see all options and some only 1 or 2. I am unsure how to go about this.
Here is the code for the dropdowns and the store precedure.
Any help would be greatly appreciated
private void BindGrid()
{
//set up arguments for the stored proc
int? FacilityID = (ddlFacility.SelectedValue.Equals("-1")) ? (int?)null : int.Parse(ddlFacility.SelectedValue);
int? SourceTypeID = int.Parse(ddlSource.SelectedValue);
int? StatusTypeID = int.Parse(ddlStatusType.SelectedValue);
//bind
ObjectResult<models.MS_spGetMatchCross_Result> ds = this.DataLayer.model.MS_spGetMatchCross(FacilityID, SourceTypeID, StatusTypeID);
gvResults.DataSource = ds;
gvResults.DataBind();
}
private void ResetForm()
{
try
{
//facility dropdown
ddlFacility.Items.Clear();
ddlFacility.DataSource = this.DataLayer.model.MS_spGetFacilityInfo(null).OrderBy(x => x.FacilityName);
ddlFacility.DataTextField = "FacilityName";
ddlFacility.DataValueField = "FacilityID";
ddlFacility.DataBind();
ddlFacility.Items.Insert(0, new ListItem("Select a facility...", "-1"));
//SourceType dropdown
ddlSource.Items.Clear();
ddlSource.DataSource = this.DataLayer.model.SourceTypes;
ddlSource.DataTextField = "Description";
ddlSource.DataValueField = "SourcetypeID";
ddlSource.DataBind();
//Match Status dropdown
ddlStatusType.Items.Clear();
ddlStatusType.DataSource = this.DataLayer.model.StatusTypes;
ddlStatusType.DataTextField = "Description";
ddlStatusType.DataValueField = "StatusTypeID";
ddlStatusType.DataBind();
BindGrid();
}
catch (Exception ex)
{
this.SetMessage(ex.ToString(), PageMessageType.Error);
AISLogger.WriteException(ex);
}
}
A very straightforward, though not exactly elegant, way would be to handle the DropDownList's OnSelectedIndexChanged event. For that to work, you'd have to make sure that each DDL whose selection will affect the contents of another DDL has the AutoPostBack property set to true (this ensures when something in the DDL changes, the page will cause a postback, allowing you to handle the change in server-side code).
In your first DropDownList's OnSelectedIndexChanged event handler (in the code-behind), you'll have the following code:
// Handle selected item or selected index
if(ddl1.SelectedItem.Text=="Selection1")
{
// Get items for DDL2
var items=GetDataForDdl2();
// Bind the data
DDL2.DataSource=items;
DDL2.DataBind();
}
You'd have similar logic for DDL2's SelectedIndexChanged event handler to then bind the items of DDL3, and so on.
For something that works nicely out of the box, check out the ASP.NET AJAX AjaxControlToolkit's CascadingDropDown: http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/CascadingDropDown/CascadingDropDown.aspx
I have a combobox control on form that pull its data (Displays and values) from some datasource. On another side I have table with one row. I want when app is lauching, combobox set selectedvalue or selecteditem to value of one column in above row. And when user has changed combobox it will persist change to row. I have tried to bind SelectedValue to this column, but it doesn't work. Combobox just sets on start to first item. What is problem?
EDIT
This is a Win Forms project.
Here is the binding code:
this.comboBoxCountries = new System.Windows.Forms.ComboBox();
this.countriesBindingSource = new System.Windows.Forms.BindingSource(this.components);
//
// comboBoxCountries
//
this.comboBoxCountries.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.searchCriteriaBindingSource, "Postcode", true));
this.comboBoxCountries.DataBindings.Add(new System.Windows.Forms.Binding("SelectedValue", this.searchCriteriaBindingSource, "CountryCode", true));
this.comboBoxCountries.DataSource = this.countriesBindingSource;
this.comboBoxCountries.DisplayMember = "Name";
this.comboBoxCountries.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxCountries.FormattingEnabled = true;
this.comboBoxCountries.Location = new System.Drawing.Point(190, 19);
this.comboBoxCountries.Name = "comboBoxCountries";
this.comboBoxCountries.Size = new System.Drawing.Size(156, 21);
this.comboBoxCountries.TabIndex = 2;
this.comboBoxCountries.ValueMember = "Code";
this.comboBoxCountries.SelectedValueChanged += new System.EventHandler(this.comboBoxCountries_SelectedValueChanged);
//
// countriesBindingSource
//
this.countriesBindingSource.DataMember = "Countries";
this.countriesBindingSource.DataSource = this.dbDataSetCountries;
//
// dbDataSetCountries
//
this.dbDataSetCountries.DataSetName = "dbDataSetCountries";
this.dbDataSetCountries.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema;
//
// searchCriteriaBindingSource
//
this.searchCriteriaBindingSource.AllowNew = false;
this.searchCriteriaBindingSource.DataMember = "SearchCriteria";
this.searchCriteriaBindingSource.DataSource = this.dbDataSetSearchCriteria;
this.searchCriteriaBindingSource.BindingComplete += new System.Windows.Forms.BindingCompleteEventHandler(this.searchCriteriaBindingSource_BindingComplete);
//
// dbDataSetSearchCriteria
//
this.dbDataSetSearchCriteria.DataSetName = "dbDataSetSearchCriteria";
this.dbDataSetSearchCriteria.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema;
EDIT2
As I have mentioned in my comment below, I have another textbox that is binded to another DataMember of same binding source and textbox working fine. It's appear with appropriate value. When I change DataMember on same datamember on which I set selectedvalue property of combobox binding it's also show a good result and work properly.
Thanks in advance!
Take a look at the DisplayMember and ValueMember properties of the combobox. You need to tell the ComboBox what member from the datasource to display in the drop down, and what value to give when SelectedValue is requested.
It sounds like your ComboBox is bound to a static list while your rows are not. You might consider using a BindingSource that you set the ComboBox and the DataGridView's DataSource to. That way when the DGV navigates to a new row, the ComboBox will be updated with the value for the new row.
Here is a link to the ComboBox on MSDN: http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.aspx
I find it out. So for managing with this issue you should remove SelectedValue databinding from visual studio data bound menu and put an appropriate code to add this databinding in some place after filling all bindingsources:
private void MainForm_Load_1(object sender, EventArgs e)
{
this.searchCriteriaTableAdapter1.Fill(this.dbDataSetCountries.SearchCriteria);
this.searchCriteriaTableAdapter.Fill(this.dbDataSetSearchCriteria.SearchCriteria);
comboBoxCountries.DataBindings.Add("SelectedValue", this.dbDataSetCountries.SearchCriteria, "CountryCode");
}
I want that my dropdownlist display first value: "-choose car-"
I succeed at this way:
protected void ddl1_DataBound(object sender, EventArgs e)
{
Convert.ToInt32(ddl1.SelectedValue);
ddl1.Items.Insert(0, new ListItem("-Choose car-", "-Choose car-" ));
}
and that's ok,the "-choose-" is in the first place but the problem now is that if I have values,for example,the dropdownlist show like that:
-Choose car-
Subaro
Fiat
Honda
The first value that display when I'm enter to the site is the Subaro,and to see the -choose car- the user need to open the dropdownlist and then he will see the -choose car- at the first place.How can I do that from the start,from the page load - the -choose car- will display at the ddl from the page load.Where I wrong at the code ?
I tried the itemlist with AppendDataBoundItems = "true" but I got an error, and when I succeed,the problem is the same like I said before.
You were on the right track with using the AppendDataBoundItems property, it should be set to true if you're databinding the list.
Your markup should look like this
<asp:DropDownList runat="server" ID="ddl1" AppendDataBoundItems="true">
<asp:ListItem Text="-Choose car-" />
</asp:DropDownList>
and your code behind probably already looks something like this
ddl1.DataSource = [your datasource goes here];
ddl1.DataBind();
This will place the Choose car text as the first option in the drop-down list and append the rest of the options below it.
Now for the more interesting part of why you were seeing the behavior you were seeing (first item not being selected). If you look at the implementation of SelectedIndex using a tool like JustDecompile (not affiliated with Telerik, just happen to use their tool) you'll see code that looks like this:
public int SelectedIndex
{
get
{
int num = 0;
num++;
while (num < this.Items.Count)
{
if (this.Items[num].Selected)
{
return num;
}
}
return -1;
}
set
{
// stuff you don't care about
this.ClearSelection();
if (value >= 0)
{
this.Items[value].Selected = true;
}
// more stuff you don't care about
}
}
As you can see, the index isn't stored anywhere, it's computed every time based on which item has the Selected property set to true. When you set the SelectedIndex to 0 in the markup and databind your datasource, it will select the 0th item in that list, in your case Subaro. When you insert a new item at the beginning of the list, Subaro is still marked as the selected item, which is why when the page loads, you see that selected and not Choose car. If you want to mark Choose car as the selected item using code, you will have to do it after you data databind your dropdown. Please note, this is just an implementation detail of how DropdownList works. It could change in future version of ASP.NET so do not write code that relies on it working this way.
Make sure that you bind the data source and insert you "-choose care-" item first before selected he first item
make sure when you insert your 1st item "-Choose car-" you make it once not on each PostBack. Check if not IsPostBack to add the 1st item.
EDIT:
Example:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
ddl1.Items.Insert(0, new ListItem("-Choose car-", "-Choose car-" ));
}
ddl1.SelectedIndex = 0;
}
You should do ddl1.Items.Insert(0, new ListItem("-Choose car-", "-Choose car-")); first, and than ddl1.SelectedIndex = 0
private void FillCar()
{
DataTable dt = GetCar();
ddl1.Items.Clear();
ddl1.DataSource = dt;
ddl1.DataTextField = "carName"; // field name in the database
ddl1.DataValueField = "CarNum"; // field name in the database
ddl1.DataBind();
ListItem li = new ListItem();
li.Text = "--Choose car--";
li.Value = "-1";
ddl1.Items.Insert(0, li);
ddl1.SelectedIndex = 0;
}
I use method like this and call it in the page load in if (!IsPostBack){}.