After much searching I have still not found a solution to this.
I have created a list in VS 2010 and bound it to a ComboBox. The DataSource property shows the entire list but the combobox on the form is empty, as is the items property of the box.
private List<string> classes = new List<string>();
private BindingList<string> bindingClasses;
classes.Add("Spinning");
classes.Add("Step");
classes.Add("Pilates");
classes.Add("Kickboxing");
classes.Add("Body Sculpting");
bindingClasses = new BindingList<string>(classes);
classesComboBox.DataSource = bindingClasses;
I have also tried adding
classesComboBox.DisplayMember = "Spinning";
and without the bindingList between to no avail.
Why is this not working?
Lose the BindingList, just set the DataSource to the List<String> itself.
List<string> classes = new List<string>();
classes.Add("Spinning");
classes.Add("Step");
classes.Add("Pilates");
classes.Add("Kickboxing");
classes.Add("Body Sculpting");
classesComboBox.DataSource = classes;
classesComboBox.SelectedItem = "Spinning";
classesComboBox.DataBind();
You need to specify when it should grab the data.
Related
I am programming UI with WPF for a month. So i am new in this world. This is my first ever post here and my motherlanguage isn't English. So if there is any mistake in my writing, sorry for that.
I have a problem with WPF and I am not able to find a solution for it. I am trying to make completely customizable DataGrid in WPF and I don't want the DataGrid to create columns or rows automatically.
I have an ObservableCollection named Sinif_Tutucu (means Class_Holder in my motherlanguage) which holds classes. These classes have the same Field and Properties, but their values are different. I am creating the columns one by one according to Fields and Properties in these classes. After this I am adding columns to DataGrid manually.
Then I am adding the rows with ItemsSource like this.
DataGrid_1.ItemsSource = Sinif_Tutucu;
This populates only properties in the DataGrid and columns made up of fields remain empty. I have searched this and i guess there is no way to bind Fields to DataGrid. Classes within Sinif_Tutucu have thousands of fields. So I can't turn fields to properties and I don't want to code the whole datagrid structure from scratch. Because WPF DataGrid structure offers many useful features which i am currently using. I am able to get Field names and their values or Property names and values. I just need to create each row myself (like columns) and populate their cells one by one with my hand with C#. Or somehow I need to convert these Fields to Properties programmatically. Is there any way to achieve this?
Supposing your class that you want to show in the datagrid looks like this
public class Data
{
public int Value;
public string Name;
public DateTime Date = DateTime.Now;
}
Because you cannot bind fields to DataGridColumns, you have to dynamically create the columns and the records. Here is a short snippet which you can use to do that. This method creates new dynamic objects in a List, which stores the same data as in your ObservableCollection. This List is set as the new ItemSource of your DataGrid. This snippet only creates DataGridTextColumns. You migth have to modify this solution, if want to use other DataGridColumns.
private void loadDataGrid()
{
List<dynamic> dataObjects = new List<dynamic>();
dynamic dataObject;
IDictionary<string, object> dataObjectValues;
var fields = typeof(Data).GetFields();
foreach (var item in Sinif_Tutucu)
{
dataObject = new System.Dynamic.ExpandoObject();
foreach (var field in fields)
{
dataObjectValues = (IDictionary<string, object>)dataObject;
dataObjectValues[field.Name] = field.GetValue(item);
}
dataObjects.Add(dataObject);
}
dataObjectValues = (IDictionary<string, object>)dataObjects[0];
foreach (var pair in dataObjectValues)
{
var binding = new Binding(pair.Key);
DataGridTextColumn col = new DataGridTextColumn() { Binding = binding, Header = pair.Key }; //You might want to use another DataGridColumn-Type
dataGrid.Columns.Add(col);
}
dataGrid.ItemsSource = dataObjects;
}
I have a windows form with many comboboxes. They all have to display the same items and I want to be able to remove items from their list of values. So I decided to try and make a List variable so I could easily remove and insert values into it. So what I did was
List<string> Ranks = new List<string>(new string[] { "values here" });
Then in my Form1Designer.cs
this.ComboBox_Rank_0.DataSource = Ranks;
I heart ValueMember and DisplayMember were good things to have, but so far it works without them. When compiled the form loads and the comboboxes have the correct values.
The problem is that when I choose a value in one combobox the others get the same value selected, as well. Any ideas?
Use a BindingList<T>
This class allows you to handle the interaction with your list separately for each of the combos
For example
List<string> names = new List<string>()
{"Steve", "Mark", "Luke", "John", "Robert"};
BindingList<string> bl1 = new BindingList<string>(names);
ComboBox_Rank_0.DataSource = bl1;
BindingList<string> bl2 = new BindingList<string>(names);
ComboBox_Rank_1.DataSource = bl2;
The BindingList<T> requires using System.ComponentModel; and notice that you don't require the new string[] syntax in the constructor of your list
I am doing simple WinForms application, and I am facing some strange problem.
My form:
It is as easy as it can be: 3 comboboxes, and two buttons - OK and Cancel.
View:
private void applyOrderButton_Click(object sender, EventArgs e)
{
List<string> testList = new List<string>()
{
"A",
"B",
"C"
};
comboBox1st.DataSource = testList;
comboBox2nd.DataSource = testList;
comboBox3rd.DataSource = testList;
comboBox1st.SelectedIndex = 2;
comboBox2nd.SelectedIndex = 1;
comboBox3rd.SelectedIndex = 0;
//Presenter.DoTest();
}
What happens after caling method applyOrderButton_Click() (it happens after Ok button is clicked) all of my comboBoxes change selected position. However, each of those comboBoxes have the same selected index - in this particular case it will be "A".
Then I change change comboBox selectedIndex using my cursour (for example I choose 3rd comboBox to show "C") the change is performed for all three comboBoxes. What I am doing wrong?
You are running across something that is present in the background of WinForms called the "CurrencyManager".
Its job is to synchronize the "current record" across all bindable controls that refer to the same data source.
For instance, if you had added a label and bound it to the same list, and bound it so that it shows a property of one of the objects, it would always show the property value of the same object you had selected in the combobox.
One bonus of this is that you could easily add a form that edits a list of objects, binding textboxes and such to the properties of one of the objects and adding a navigator that allows you to move to the next or previous row. You would not have to manually ensure all textboxes refer to the correct object, the CurrencyManager would do all this for you.
However, in your case, since you bound the same data source to all three comboboxes, the CurrencyManager will ensure all three select the same row. If you select a new row in one of the comboboxes, the CurrencyManager will go and fix all the others to refer to the same row.
You can fix this in various ways:
You can override the binding context for each combobox:
comboBox2nd.BindingContext = new BindingContext();
comboBox3rd.BindingContext = new BindingContext();
Note that if you go this route you need to do this before assigning the SelectedIndex or SelectedItem properties, otherwise the CurrencyManager will have updated the other two comboboxes before you assigned new BindingContexts.
You can assign distinct data sources to each combobox:
combobox2nd.DataSource = testList.ToList();
combobox3rd.DataSource = testList.ToList();
Just assign new context to other ComboBoxes like that:
List<string> testList = new List<string>()
{
"A",
"B",
"C"
};
comboBox1st.DataSource = testList;
comboBox2nd.BindingContext = new BindingContext();
comboBox2nd.DataSource = testList;
comboBox3rd.BindingContext = new BindingContext();
comboBox3rd.DataSource = testList;
comboBox1st.SelectedIndex = 2;
comboBox2nd.SelectedIndex = 1;
comboBox3rd.SelectedIndex = 0;
The CurrencyManager is used to keep data-bound controls synchronized with each other (showing data from the same record). The CurrencyManager object does this by managing a collection of the bound data supplied by a data source. For each data source associated with a Windows Form, the form maintains at least one CurrencyManager. Because there may be more than one data source associated with a form, the BindingContext object manages all of the CurrencyManager objects for any particular form. More broadly, all container controls have at least one BindingContext object to manage their CurrencyManagers.
This may be a very simple question but I realized I could not get it work.
I have a Winform combo box with datasource as a List<int>
combo.DataSource = intList;
What do I put for .DisplayMember and .ValueMember in order to simply have a list of integer values? Not setting them will display nothing.
I have worked with other List<myObj> in which DisplayMember and ValueMember are myObj's properties. How about simple data type like int, string?
When retrieving the selected item, one could simply cast (int)(combo.SelectedItem) or have to go through the property corresponding to ValueMember?
The problem does not occur because you have a list of integers, it probably occurs because you add items to the list after assigning it to the .DataSource property. List does not have a mechanism to notify its container when items are added to or removed from it.
Either add items to the list before assigning it to the .DataSource property, or use a wrapper like BindingSource as Krishnraj Rana suggested.
Here BindingSource comes into picture. You can use it like this.
BindingSource bSource = new BindingSource();
bSource.DataSource = new List<int> { 1, 2, 3 };
combo.DataSource = bSource;
Though you can set datasource of combobox directly with list. like this -
combo.DataSource = intList;
This also works perfectly fine.
You can add items from list using foreach like this.
foreach (var v in intList)
{
comboBox1.Items.Add(v.ToString());
}
i have two different Lists.
List<MyClass> list1 = new List<MyClass>();
List<OtherClass> list2 = new List<OtherClass>();
I bind one of them to a xtragrid form devexpress:
gridControl.DataSource = list1;
That works. Now i want to change the list but the columns doesn't change.
Can someone help me?
Call gridView.PopulateColumns().