This is really strange. I want to select a State and load Cities from that State in another combobox.
It's working EXCEPT when selecting the first item in the combobox:
Here's my entire class. The if statement in the selectedIndexChanged is to make sure that something is selected. The problem is that if I set that to cmbState.SelectedIndex >= 0 then an exception is raised because on initial load the comboBox doesn't has a .State variable there and not a .Value.
I don't know if this makes any sense.
private void MainForm_Load(object sender, EventArgs e)
{
LoadDepartmentsToComboBox();
}
private void LoadCitiesToComboBox(long StateID)
{
cmbCity.DataSource = null;
CityRepository cityRepo = new CityRepository();
cmbCity.DataSource = cityRepo.FindAllCities().Where(c => c.IDState == StateID);
cmbCity.DisplayMember = "Name";
cmbCity.ValueMember = "ID";
}
private void LoadDepartmentsToComboBox()
{
cmbState.DataSource = null;
StateRepository stateRepo = new StateRepository();
cmbState.DataSource = stateRepo.FindAllStates();
cmbState.DisplayMember = "Name";
cmbState.ValueMember = "ID";
}
private void cmbState_SelectedIndexChanged(object sender, EventArgs e)
{
if (cmbState.SelectedIndex > 0)
{
LoadCitiesToComboBox(Convert.ToInt64(cmbState.SelectedValue));
}
}
If I do use cmbState.SelectedIndex >= 0 then I receive this exception:
Unable to cast object of type
'DocumentScannerDanyly.State' to type
'System.IConvertible'.'System.IConvertible'.
When I don't use the SelectedIndex >= 0 and use plain old >0 then everything works except when selected the first item, which does nothing; understandably because it doesn't take the first item into account.
Thanks a lot for the help.
Don't assign the Display member & the Value member in each load, just assign them once in constructor for example.
add ToList() to the result which will assign to DataSource,
Complex DataBinding accepts as a data source either an IList or an IListSource.
check this.
Related
I am creating a little ASP.NET app and have a problem with one field value.
I have defined my enum in a class:
class Column
{
public enum Type {
Undefined = 0,
Integer = 1,
ShortDate = 2,
Etc = 3 }
// some other stuff
}
The app contains some controls to enter properties of a column, namely a dropdownlist for choosing the column type and some unimportant others. And when all properties are properly entered, SaveButton in enabled to save the column type info into a listbox. My Default.aspx.cs contains:
private Column.Type selectedType;
protected void Page_Load(object sender, EventArgs e)
{
// fill the ColumnTypeDropDownList (from the Column.Type enum)
if (!IsPostBack)
{
foreach (Column.Type ct in Enum.GetValues(typeof(Column.Type)))
{
ColumnTypeDropDownList.Items.Add(new ListItem(ct.ToString()));
}
}
}
protected void ColumnTypeDropDownList_SelectedIndexChanged(object sender, EventArgs e)
{
PrepareToSave();
}
// also called from other controls events, therefore in a separate method
private void PrepareToSave()
{
// control if all needed properties are entered and set the field
if ((ColumnNameTextBox.Text != "") && (ColumnTypeDropDownList.SelectedValue != Column.Type.Undefined.ToString()))
{
foreach (Column.Type ct in Enum.GetValues(typeof(Column.Type)))
{
if (ct.ToString() == ColumnTypeDropDownList.SelectedValue) selectedType = ct;
}
SaveButton.Enabled = true;
}
}
protected void SaveButton_Click(object sender, EventArgs e)
{
ColumnsListBox.Items.Add(selectedType.ToString()); // always writes "Undefined"
}
The problem is that it always writes "Undefined" into the listbox, even though another type was selected from the dropdownlist. I tried to add the item into the listbox inside the PrepareToSave() method and that works correctly, but I need it outside. On the other hand, the condition controlling if any other value than Undefined is selected from the dropdownlist works well. It seems that the field selectedType has the correct selected value only inside the PrepareToSave() method.
AutoPostBack of all the controls is enabled.
Am I missing something about the enums or do you have any tips how to fix it? Thanks.
Your problem is in the line...
ColumnTypeDropDownList.Items.Add(new ListItem(ct.ToString()));
..namely in new ListItem(ct.ToString()). When you use this constructor of the ListItem class, you create an item with Value set to null. Later you compare against the value:
if (ct.ToString() == ColumnTypeDropDownList.SelectedValue) selectedType = ct;
Since Value of each of the items is null, ColumnTypeDropDownList.SelectedValue is also null and your comparison fails. That should be also easily figured out in a debugger.
The correct list item constructor for you is
ListItem listItem = new ListItem(ct.ToString(), ct.ToString());
As an additional issue, you have to call PrepareToSave in SaveButton_Click, since the selectedType field will have lost its value across requests. PrepareToSave will rebuild that value.
That's most probably because of your if condition as pointed below
if ((ColumnNameTextBox.Text != "") && (ColumnTypeDropDownList.SelectedValue != Column.Type.Undefined.ToString()))
{
Instead of ColumnNameTextBox.Text != "" use !string.IsNullOrEmpty(ColumnNameTextBox.Text)
Just another tip:
Use GetNames instead of GetValues in your foreach loop:
foreach (var ct in Enum.GetNames(typeof(Column.Type)))
{
//do your stuff.
}
If you want to use AutoPostBack ...
Add a hidden control to your page.
In your PrepareToSave(); method you just can add the selectetType like yourControlName.Text = ct;
And change your save handler to this ....
protected void SaveButton_Click(object sender, EventArgs e)
{
// Read the value of the hidden control
ColumnsListBox.Items.Add(yourControlName.Text);
}
I have a problem in manipulating comboBoxes. There are three comboboxes. If I change the selected index on the 1st combobox then values in the 2nd and 3rd should be updated. An
IndexOutOfRange exception occurs. I know, in start, I have 3 data items... when I change the index of the 1st then the 2nd must have 8 to 9 values. Here occur exception
2nd combobox have 3 values.
now if 1st is changed then here occur exception
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox3.SelectedIndex == 1)
{
comboBox1.Items[0]="Kilometer";
comboBox1.Items[1]="Meter";
comboBox1.Items[2]="Centimeter";
comboBox1.Items[3]="Millimeter";
comboBox1.Items[4]="Mile";
comboBox1.Items[5]="Yard";
comboBox1.Items[6]="Foot";
comboBox1.Items[7]="Inch";
comboBox1.Items[8] = "Nautical Mile";
comboBox2.Items[0] = "Meter";
comboBox2.Items[1] = "Centimeter";
comboBox2.Items[2] = "Millimeter";
comboBox2.Items[3] = "Mile";
comboBox2.Items[4] = "Yard";
comboBox2.Items[5] = "Foot";
comboBox2.Items[6] = "Inch";
comboBox2.Items[7] = "Nautical Mile";
comboBox2.Items[8] = "Kilometer";
}
else if (comboBox3.SelectedIndex == 2)
{
comboBox1.Items[0] = "Metric ton";
comboBox1.Items[1] = "Kilogram";
comboBox1.Items[2] = "Gram";
comboBox1.Items[3] = "Milligram";
comboBox1.Items[4] = "Mcg";
comboBox1.Items[5] = "Long ton";
comboBox1.Items[6] = "Short ton";
comboBox1.Items[7] = "Stone";
comboBox1.Items[8] = "Pound";
comboBox1.Items[9] = "Ounce";
}
}
When you can it's often better practice to avoid accessing and changing objects by their index in a collection, e.g. when you can use foreach, use that rather than a for with the index.
For instance, in this case you can create a List from an array (defined in the code of the objects), and set the .Items collection to this. This avoids the usage of any numbers. You can also store references to the comboBox1 items and use .SelectedItem rather than .SelectedIndex, for instance if there was ever any chance that more items would be added to that combo box.
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox3.SelectedIndex == 1)
{
comboBox1.Items.Clear();
comboBox1.Items.Add("Kilometer");
// and so on
comboBox2.Items.Clear();
comboBox2.Items.Add("Meter");
// and so on
}
else if(comboBox3.SelectedIndex == 2)
{
comboBox1.Items.Clear();
comboBox1.Items.Add("Metric ton");
// and so on
}
}
Alternatively
private String[] comboBoxOneItemsArraySetOne = { "SetOneItem1", "SetOneItems2" };
private String[] comboBoxOneItemsArraySetTwo = { "SetTwoItem1", "SetTwoItems2" };
private String[] comboBoxTwoItemsArray = { "Item1", "Items2" };
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox3.SelectedIndex == 1)
{
comboBox1.Items.Clear();
foreach(String s in comboBoxOneItemsArraySetOne)
{
comboBox1.Items.Add(s);
}
comboBox2.Items.Clear();
foreach(String s in comboBoxTwoItemsArray)
{
comboBox2.Items.Add(s);
}
}
else if(comboBox3.SelectedIndex == 2)
{
comboBox1.Items.Clear();
foreach(String s in comboBoxOneItemsArraySetTwo)
{
comboBox1.Items.Add(s);
}
}
}
I assume you mean ArgumentOutOfRangeException. It is likely because you are directly assigning to non-existent index locations. You need to use Add() or AddRange() to add the items.
comboBox1.Items.Add("Metric ton");
//...
comboBox1.Items.Add("Ounce");
Winforms ComboBox.Items is of type ObjectCollection. Use of index[0] notation is valid for values that already exist, but not for adding.
The same exception can also be caused by setting ComboBox.SelectedIndex to a value that is out of range. Remember the collection index is zero-based, which means if you have 3 items, they use indexes [0..2]
You can also clear the items with Items.Clear() or remove specific Items with Items.Remove("something") or Items.RemoveAt(i)
http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.objectcollection.add(v=vs.110).aspx
public void DD_Location()
{
var ctx = new LCCDB_EF();
var query = ctx.tbl_Location;
CB_Location.DataContext = query.ToList();
}
private void CB_Location_DropDownClosed(object sender, EventArgs e)
{
textbox_test.Text =CB_Location.Text;
}
Output in Textbox
System.Data.Entity.DynamicProxies.Location_5E43C6C196972BF0754973E48C9C941092D86818CD94005E9A759B70BF6E48E6
Try this
if(null != CB_Location.SelectedItem)
textbox_test.Text = CB_Location.SelectedItem.ToString();
Without seeing your XAML I can't be sure, but are you sure you've bound the list correctly? Try setting the Items property of combobox to your list, rather than the data context. Depending on what the type is and what you'd like to bind the text to, you may need to set the DisplayMemberPath property as appropriate, too.
I have a dropdown in my webpage, which always returns the value 0 as the selected index no matter whichever item the user selects. I have populated the dropdown using a DB query. And I am populating in on Page_Load method in my page. The code shown below does the specified work: int danceid;
protected void Page_Load(Object sender, EventArgs e)
{
if (!IsPostBack)
{
PopulateDanceDropDown();
}
}
private void PopulateDanceDropDown()
{
DataTable dt = new DataTable();DataRow row = null;
dt.Columns.Add("Did", Type.GetType("System.Int32"));
dt.Columns.Add("DName", Type.GetType("System.String"));
var dancer_dance = (from dd in context.DANCER_AND_DANCE
where dd.UserId == dancerId
select new
{
Value = dd.DanceId,
Text = dd.DanceName
}).ToList();
foreach (var dndd in dancer_dance)
{
row = dt.NewRow();
row["Did"] = dndd.Value;
row["DName"] = dndd.Text;
dt.Rows.Add(row); dances.DataSource = dt;
dances.DataTextField = dt.Columns[1].ToString();
if (!IsPostBack)
{
dances.DataBind();
}
}
protected void changeIndex(object o, EventArgs e)
{
danceid = dances.SelectedIndex;
}
protected void dropthedance(object o, EventArgs e)
{
int danceIDFromDropDown = danceid;
var dancer_dance = from dd in context.DANCER_AND_DANCE
where dd.DanceId == danceIDFromDropDown
select dd;
foreach (var dndd in dancer_dance)
{
context.DANCER_AND_DANCE.DeleteOnSubmit(dndd);
}
try
{
context.SubmitChanges();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
The line int danceIDFromDropDown = danceid; in the method dropthedance always has the value 0. Pleaseeeeeeeeeeeeee help someone
Are you sure that you want to be using the index as the ID? Typically, you're going to want to set the actual ID from your database as the DataValueField and then you can grab the value that way.
But I also noticed that you grab the index and place it into a variable on the indexchanged event and then you try to use that value in a different method. I'm assuming that danceid is an attribute somewhere not shown here. At any rate, the value isn't persisting through postbacks. Instead of trying to store it in a variable like you would on a desktop application, try adding EnableViewState="True" to your dropdown control. Then get that index on your submit handler directly. Or if you really want to store it in a variable, then try persisting the value of that variable by storing it in the session or caching it, then pull from that cache/session variable when it comes time to actually use the value.
But again, it might be better practice to place the danceid in the listitem object itself. Just the though of basing IDs on item indexes makes me shudder, especially when you populating the list from a database, because what happens when you add a new item to that list in the library and then try to sort them by name... then your indices become useless.
Replace
int danceIDFromDropDown = danceid;
with
int danceIDFromDropDown = dances.SelectedIndex;
It may work.
Currently my repository returns an IQueryable object that lists the data from my DB and I bind this to a BindingSource for use in a grid:
public void BindTo(IQueryable elements)
{
BindingSource source = new BindingSource();
source.CurrentChanged += new EventHandler(source_CurrentChanged);
source.DataSource = elements;
elementNavigator.BindingSource = source;
elementGridView.DataSource = source;
}
This works great. However I am wanting to do some stuff when a user clicks an row in the grid. I'm struggling to identify the element that the user is selecting. I have the following:
In my view:
private void source_CurrentChanged(object sender, EventArgs e)
{
_presenter.ElementChanged(sender, e);
}
In my presenter:
public void ElementChanged(object sender, EventArgs e)
{
BindingSource source = (BindingSource)sender;
// Here I need to get the ID of the selected element in the source.Current property.
// HOW?
}
This seems to work ok - and I can see when debugging that source.Current contains the data:
? source.Current
{ BodyId = 1, IsInUse = true, IsValid = true, CreateDate = {04/07/2006 09:31:59}, LastUpdateDate = {04/07/2006 09:31:59}, StatusDescShort = "Exist" ... }
BodyId: 1
CreateDate: {04/07/2006 09:31:59}
IsInUse: true
IsValid: true
LastUpdateDate: {04/07/2006 09:31:59}
StatusDescShort: "Exist"
but I am at a loss as how I might access the value of BodyId. I've a feeling I'm missing something really obvious here (not the first time).
I'm surprised you're not using something like IQueryable<MyType>.
Because then it would be a simple matter of casting: source.Current as MYType
And maybe eliminate an in-between DataRowView