List<Customer> _customers = getCustomers().ToList();
BindingSource bsCustomers = new BindingSource();
bsCustomers.DataSource = _customers;
comboBox.DataSource = bsCustomers.DataSource;
comboBox.DisplayMember = "name";
comboBox.ValueMember = "id";
Now how do I set the combobox's Item to something other than the first in the list?
Tried
comboBox.SelectedItem = someCustomer;
...and lots of other stuff but no luck so far...
You should do
comboBox.SelectedValue = "valueToSelect";
or
comboBox.SelectedIndex = n;
or
comboBox.Items[n].Selected = true;
Your binding code is not complete. Try this:
BindingSource bsCustomers = new BindingSource();
bsCustomers.DataSource = _customers;
comboBox.DataBindings.Add(
new System.Windows.Forms.Binding("SelectedValue", bsCustomers, "id", true));
comboBox.DataSource = bsCustomers;
comboBox.DisplayMember = "name";
comboBox.ValueMember = "id";
In most cases you can accomplish this task in the designer, instead of doing it in code.
Start by adding a data source in the "Data Sources" window in Visual Studio. Open it from menu View > Other Windows > Data Sources. Add an Object data source of Customer type. In the Data Sources you will see the customer's properties. Through a right click on the properties you can change the default control associated to it.
Now you can simply drag a property from the Data Sources window to you form. Visual Studio automatically adds A BindingSource and a BindingNavigator component to your form when you drop the first control. The BindingNavigator is optional and you can safely remove it, if you don't need it. Visual Studio also does all the wire-up. You can tweak it through the properties window. Sometimes this is required for combo boxes.
There's only one thing left to do in your code: Assign an actual data source to the binding source:
customerBindingSource.DataSource = _customers;
this works for me
bsCustomers.Position = comboBox.Items.IndexOf(targetCustomer);
Related
I'm using a DataGridView to display string values using a string wrapper class, a BindingSource and a BindingList.
When launching the app, however, the values are only visible after clicking on the rows. I already tried to look in all possible style property to see where the initial black color comes from, without success.
Initial look:
After clicking (funny colors to try to understand which style does what) or minimizing and maximizing the window:
Form code (already tried some variants here, final version will not look like this):
private BindingSource dataSource;
private BindingList<StringValue> bindingList;
private List<StringValue> list = new List<StringValue>();
public MainForm()
{
InitializeComponent();
grdCodes.AutoGenerateColumns = false;
bindingList = new BindingList<StringValue>(list);
dataSource = new BindingSource(bindingList, null);
grdCodes.DataSource = dataSource;
// Load += MainForm_Load;
x();
}
//private void MainForm_Load(object sender, EventArgs e)
//{
// grdSupiCodes.AutoGenerateColumns = false;
// bindingList = new BindingList<StringValue>(list);
// dataSource = new BindingSource(bindingList, null);
// grdSupiCodes.DataSource = dataSource;
//}
private void x()
{
list.Add(new StringValue("AAAAAAAAAAAA"));
list.Add(new StringValue("BBBBBBBBBBBB"));
list.Add(new StringValue("CCCCCCCCCCCC"));
// none of the below work:
grdCodes.ResetBindings();
// grdCodes.Update();
// grdCodes.Refresh();
// grdCodes.DataSource = null;
// grdCodes.DataSource = dataSource;
}
My question is, how to make the app launch already displaying the values in the grid? I can post the designer code if it helps, but there is nowhere a black color defined (form background is DarkGrey, visible under the grid).
Given the scenario described:
An empty List<class> (INotifyPropertyChanged is most probably not implemented) is added to a BindingList of the same type.
The empty BindingList is set as the DataSource of a BindingSource.
The BindingSource (bound to the still empty BindingList) is set as the DataSource of a DataGridView
Some new Items are added to the List afterwards.
In this scenario, it's simple to verify that the BindingSource doesn't receive any ListChanged events just subscribing to the event: the event is never raised.
Even though the Bindinglist.Count property is incremented to the number of items added, this count is only reporting the number of items contained in the source List<class>, which doesn't notify changes.
The DataGridView can actually show the new content, but the underlying DataSource - the internal List generated by the BindingSource - is disconnected from the original source: when a Row is selected in the DataGridView, the most common result is that an IndexOutOfRangeException is raised, since we're trying to access a non synchronized Item from the internal Dictionary, accessing an Item at index -1, in practice.
Several methods can be used to synchronize the internal collections:
Adding the new Items directly to the BindingList instead of the source List<class>: the BindingList will generated ListChanged events in the linked BindingSource, synchronizing the collections and the source List<class> will be updated anyway.
bindingList.Add(new StringValue("StringValue1"));
bindingList.Add(new StringValue("StringValue2"));
bindingList.Add(new StringValue("StringValue3"));
If new Items need to be added to the original List<class>, for some reason, call the BindingList.ResetBinding() or the BindingSource.ResetBinding(false) methods after the new Items have been added; this will generate the ListChanged event and the synchronization will be performed as a consequence:
list.Add(new StringValue("StringValue1"));
list.Add(new StringValue("StringValue2"));
list.Add(new StringValue("StringValue3"));
bindingList.ResetBindings();
// Or...
// bindingSource.ResetBinding(false);
Instead of using the BindingList<class> object directly as the DataSource of the BindingSource, we can set the DataSource to the corresponding Type, so the DataGridView will bind its Columns to the data source using either the DataPropertyName property, if AutoGenerateColumns = false, or generate Columns from the source object(s) Properties Names, when AutoGenerateColumns = true:
BindingList bindingList = new BindingList<StringValue>(list);
BindingSource bindingSource = new BindingSource(typeof(BindingList<StringValue>), null);
dataGridView.DataSource = bindingSource;
After the new Items have been added to the source List<class>, set the DataSource of the BindingSource to the BindingList, causing the internal collection to re-synchronize:
list.Add(new StringValue("StringValue1"));
list.Add(new StringValue("StringValue2"));
list.Add(new StringValue("StringValue3"));
bindingSource.DataSource = bindingList;
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.
I want to fill combobox content with my list in WPF. I can do it normally in winform but wpf looks a bit different..
I dont create any code in XAML. whole controls create dynamically and at run time..
so here is my code
cmbKriterKategori is a combobox.
cmbKriterKategori.DisplayMemberPath = "Value";
cmbKriterKategori.SelectedValuePath = "Key";
cmbKriterKategori.ItemsSource = yHelper.GetCriterList().ToList();
an error occours
Items collection must be empty before using ItemsSource.
and I also tried like that
cmbKriterKategori.DisplayMemberPath = "Value";
cmbKriterKategori.SelectedValuePath = "Key";
cmbKriterKategori.DataContext = yHelper.GetCriterList().ToList();
it doesnt occour any error but combobox hasnt any item..
yHelper.GetCriterList().ToList(); this function returns List>
and yHelper.GetCriterList() returns Dictionary
I used that code in winform and it works..
cmbKriterKategori.DisplayMember = "Value";
cmbKriterKategori.ValueMember ="Key";
cmbKriterKategori.DataSource = yhelper.GetCriterList().ToList();
So, What is the problem?
you have to clear your combo items so the Items collection must be empty before using ItemsSource exception won't be thrown
cmbKriterKategori.Items.Clear();
cmbKriterKategori.DisplayMemberPath = "Value";
cmbKriterKategori.SelectedValuePath = "Key";
cmbKriterKategori.ItemsSource = yHelper.GetCriterList().ToList();
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 have a problem with the UltraGrid control from Infragistics. I have created a ultracombobox with a few values in it:
UltraCombo ultraComboPaneel = new UltraCombo();
ultraComboPaneel.DataSource = articleList;
ultraComboPaneel.ValueMember = "ArticleID";
ultraComboPaneel.DisplayMember = "Name";
Now I have an UltraGrid, and I want to put the ultraCombo in a cell so I can choose one of the items of the ultracombo as a cell value. I tried it both in code and in the ultragrid designer but i can't seem to find a way to do it.
Any of you got an idea? More information can be provided if needed
Edit:
I found something like
UltraGridColumn ugc = ultraGridTypePaneel.DisplayLayout.Bands[0].Columns.Add("combo");
ultraGridTypePaneel.DisplayLayout.Bands[0].Columns["combo"].EditorControl = ultraComboPaneel;
I feel I'm on the right way but it is still not showing on the screen...
The UltraCombo provides a great deal of functionality. If all you need is the ability to choose an item from a list, you might find the grid's ValueLists provide a better solution.
Here's some code to get you started:
private void myGrid_InitializeLayout(object sender, Infragistics.Win.UltraWinGrid.InitializeLayoutEventArgs e)
{
const string colorValueList = #"ColorValueList";
if (!e.Layout.ValueLists.Exists(colorValueList))
{
ValueList svl = e.Layout.ValueLists.Add(colorValueList);
svl.ValueListItems.Add(1, "Red");
svl.ValueListItems.Add(2, "Green");
svl.ValueListItems.Add(3, "Blue");
}
e.Layout.Bands[0].Columns["Color"].ValueList = e.Layout.ValueLists[colorValueList];
}
You could find at the link below some approaches that you could use to put a DropDown into a UltraGrid cell:
http://devcenter.infragistics.com/Support/KnowledgeBaseArticle.aspx?ArticleID=7841
Going back to your current code snippet - you are almost there:
First you should set the binding context of your UltraCombo to the BindingContext of the form the your UltraCombo will be used like:
ultraComboPaneel.BindingContext = this.BindingContext;
Please note that setting binging context should happen prior setting your control to be EditorControl. One more thing that I noticed is that the property currently is changed to EditorComponent so I believe that you are using older version of the Infragistics components. However you should still be able to use the very same approach. I have created small code snippet showing the above with code:
public partial class Form1 : Form
{
UltraCombo uc;
public Form1()
{
InitializeComponent();
DataTable dt = new DataTable();
dt.Columns.Add("Int", typeof(int));
dt.Rows.Add(1);
dt.Rows.Add(1);
dt.Rows.Add(1);
DataTable dtt = new DataTable();
dtt.Columns.Add("Int", typeof(int));
dtt.Rows.Add(2);
dtt.Rows.Add(2);
dtt.Rows.Add(2);
uc = new UltraCombo();
uc.BindingContext = this.BindingContext;
uc.DataSource = dtt;
ultraGrid1.DataSource = dt.DefaultView;
}
private void ultraGrid1_InitializeLayout(object sender, Infragistics.Win.UltraWinGrid.InitializeLayoutEventArgs e)
{
e.Layout.Bands[0].Columns[0].EditorComponent = uc;
}
}
Hope this helps.
I use the Ultra Dropdown instead.
dim udd As UltraDropDown
udd = New UltraDropDown
With udd
'add data binding or value list items here
End With
Me.ultragrid.DisplayLayout.Bands(0).Columns("Column Name").ValueList = udd
The key is the last line that assigns the "Value List" of the ultra grid column to the Drop down control.