Binding a generic List<string> to a ComboBox - c#

I have a ComboBox and I want to bind a generic List to it. Can anyone see why the code below won't work? The binding source has data in it, but it won't fill the ComboBox data source.
FillCbxProject(DownloadData Down)
{
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = Down.ProjectList;
cbxProjectd.DataSource = bindingSource;
}
On a side note: Is it bad to pass around an instance of a class?
Thanks!

You need to call the Bind method:
cbxProjectd.DataBind();
If this is for winforms then you need to make sure what you have is being called, the following works:
BindingSource bs = new BindingSource();
bs.DataSource = new List<string> { "test1", "test2" };
comboBox1.DataSource = bs;
Although you can set the ComboBox's DataSource directly with the list.

this is the simple way (it works correctly):
List<string> my_list = new List<string>();
my_list.Add("item 1");
my_list.Add("item 2");
my_list.Add("item 3");
my_list.Add("item 4");
my_list.Add("item 5");
comboBox1.DataSource = my_list;

Here is a rather simple way that doesn't use BindingSource:
first, add the generic list of string, perhaps to a "consts/utils" class:
public static List<string> Months = new List<string>
{
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
And here's how you add those strings to a combo box:
comboBoxMonth.Items.AddRange(UsageRptConstsAndUtils.Months.ToArray<object>());

BindingSource bs = new BindingSource();
bs.DataSource = getprojectname();
comboBox1 = new ComboBox();
comboBox1.DataSource = bs;

Using Yuriy Faktorovich's code above as a basis, here is how to get a list of dates in LongDateString format for a given number of weeks, and assign them to a combo box. This uses "Monday" but you can simply replace "Monday" with any other DOW to suit your purposes:
private void PopulateSchedulableWeeks()
{
int WEEKS_COUNT = 13;
List<String> schedulableWeeks = PlatypusUtils.GetWeekBeginnings(WEEKS_COUNT).ToList();
BindingSource bs = new BindingSource();
bs.DataSource = schedulableWeeks;
comboBoxWeekToSchedule.DataSource = bs;
}
public static List<String> GetWeekBeginnings(int countOfWeeks)
{
// from http://stackoverflow.com/questions/6346119/datetime-get-next-tuesday
DateTime today = DateTime.Today;
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
int daysUntilMonday = ((int)DayOfWeek.Monday - (int)today.DayOfWeek + 7) % 7;
DateTime nextMonday = today.AddDays(daysUntilMonday);
List<String> mondays = new List<string>();
mondays.Add(nextMonday.ToLongDateString());
for (int i = 0; i < countOfWeeks; i++)
{
nextMonday = nextMonday.AddDays(7);
mondays.Add(nextMonday.ToLongDateString());
}
return mondays;
}
...and, if you want to add the actual date to the combo box, too, you can use a Dictionary like so:
int WEEKS_TO_OFFER_COUNT = 13;
BindingSource bs = new BindingSource();
Dictionary<String, DateTime> schedulableWeeks = AYttFMConstsAndUtils.GetWeekBeginningsDict(WEEKS_TO_OFFER_COUNT); bs.DataSource = schedulableWeeks;
comboBoxWeekToSchedule.DataSource = bs;
comboBoxWeekToSchedule.DisplayMember = "Key";
comboBoxWeekToSchedule.ValueMember = "Value";
public static Dictionary<String, DateTime> GetWeekBeginningsDict(int countOfWeeks)
{
DateTime today = DateTime.Today;
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
int daysUntilMonday = ((int)DayOfWeek.Monday - (int)today.DayOfWeek + 7) % 7;
DateTime nextMonday = today.AddDays(daysUntilMonday);
Dictionary<String, DateTime> mondays = new Dictionary<String, DateTime>();
mondays.Add(nextMonday.ToLongDateString(), nextMonday);
for (int i = 0; i < countOfWeeks; i++)
{
nextMonday = nextMonday.AddDays(7);
mondays.Add(nextMonday.ToLongDateString(), nextMonday);
}
return mondays;
}

If anyone finds this necro thread, make sure your list does not contain null items.
Otherwise binding will fail silently!
//This will not work!
comboBox1.DataSource = new List<string> { "test1", null, "test2" };
//This is legit!
comboBox1.DataSource = new List<string> { "test1", "", "test2" };

Related

Replacing labels c# wpf

created a sports table that shows different statistics sorted by one property. When sorting for a different property I created completely new labels that just sit on top of the old ones instead of replacing them.
This is ran when a button is pressed:
private void Points_Order(object sender, RoutedEventArgs e)
{
List<Team> leagueTeams = new List<Team>();
using (StreamReader sr = new StreamReader("TXT1.txt"))
{
using (JsonReader jr = new JsonTextReader(sr))
{
JsonSerializer js = new JsonSerializer();
leagueTeams = js.Deserialize<List<Team>>(jr);
}
}
List<Team> sortedList = leagueTeams.OrderByDescending(o => o.points).ToList(); //orders the keagueTeams list by points and stores in a new list using linq
List<Label> TeamLabels = new List<Label>(); //makes list of labels that show the teams
List<string> Names = new List<string>(); //Creates a list for the names
List<Label> gamesPlayedLabels = new List<Label>();
List<int> GamesPlayed = new List<int>();
foreach (var properties in sortedList)
{
Names.Add(properties.name);//adds the name of each object into the Names list
GamesPlayed.Add(properties.gamesPlayed);
}
for (int i = 0; i < 20; i++)
{
string nameLab = Names[i];
TeamLabels.Add(new Label { Height = 100, Width = 100, Content = nameLab }); //sets position of the name labels
Canvas.SetLeft(TeamLabels[i], 0);
Canvas.SetTop(TeamLabels[i], (i * 19) + 19);
canvas1.Children.Add(TeamLabels[i]);
string played = Convert.ToString(GamesPlayed[i]);
gamesPlayedLabels.Add(new Label { Height = 100, Width = 100, Content = played });
Canvas.SetLeft(gamesPlayedLabels[i], 112);
Canvas.SetTop(gamesPlayedLabels[i], (i * 19) + 19);
canvas1.Children.Add(gamesPlayedLabels[i]);
}
}
When a second button is pressed the exact same code is ran but apart from
List<Team> sortedList = leagueTeams.OrderByDescending(o => o.points).ToList()
it is
List<Team> sortedList = leagueTeams.OrderBy(o => o.name).ToList();
so the question is can you replace existing labels so the table can be sorted?

C# simply chart binding

The idea is to simply to plot arrD[i] in a chart called chart5 SeriesA. The issue is that nothing is plotted in the windows form. Maybe someone could help. Many thanks.
chart5 = new Chart();
Series SeriesA = new Series();
Dictionary<int, double> value5 = new Dictionary<int, double>();
for (int i = 0; i < monthCount; i++)
{
value5.Add(i, arrD[i]);
}
SeriesA.XValueMember = "Location";
SeriesA.YValueMembers = "Value";
chart5.DataSource = value5;
chart5.Series.Add("SeriesA");
You do not add the series you created to your chart.
Try this code :
Series SeriesA = new Series();
SeriesA.Points.DataBind(arrD, "Location", "Value", "");
chart5.Series.Add(SeriesA);
Note that we add SeriesA and not "SeriesA"
Ok, I simplified the binding (which works well now) as well as the loop for hiding the zero values. But how to print now the modified chart without zero values .. many thanks.
chart7.Series["Series3"].ChartType = SeriesChartType.Line;
chart7.Series["Series3"].Points.DataBindXY(xVal, arrDouble3);
foreach (Series series in chart7.Series)
{
foreach (DataPoint arrP in series.Points)
{
if (arrP.YValues.Length > 0 && (double)arrP.YValues.GetValue(0) == 0)
{
arrP.IsValueShownAsLabel = false;
}
}
}
chart7.Series["Series3"].Points.DataBindXY(xVal, arrP); ????

Sorting issue when using combobox with item and keeping itemdata in sortedlist type

I have a project that keeping items and itemdata(number) with a sorted why.
I have 2 objects:
1.sorted Combobox that keeps the items(names)
2.sortedlist that keeps the item(name) as key and itemdata(number) as value.
For some reason some character(for example "-") is not sorted the same way in the combo and in the sortedlist.the combo keeping the string with "-" in the first row or the group while in the sortedlist its located in the last row of the group.
this is my code:
public partial class Form1: Form
{
public Form1()
{
InitializeComponent();
}
SortedList<object, object> sortedvbcombo = new SortedList<object, object>();
private void Form1_Load(object sender, EventArgs e)
{
Data[] D = new Data[5];
D[0] = new Data();
D[0].name = "BABA";
D[0].number = 1000;
D[1] = new Data();
D[1].name = "B-REAL";
D[1].number = 1001;
D[2] = new Data();
D[2].name = "BCCDC";
D[2].number = 1002;
D[3] = new Data();
D[3].name = "BAAAAA";
D[3].number = 1003;
D[4] = new Data();
D[4].name = "BFFFFDS";
D[4].number = 1004;
comboBox1.Sorted = true;
for (int i = 0; i < D.Count(); i++)
{
comboBox1.Items.Add(D[i].name);
sortedvbcombo.Add(D[i].name, D[i].number);
}
}
}
struct Data
{
public string name;
public int number;
}
the result for combo box:
B-REAL
BAAAAA
BABA
BCCDC
BFFFFDS
the result for sortedlist:
BAAAAA
BABA
BCCDC
BFFFFDS
B-REAL
why it's not sorting in the same way and if it is possible to align it from the sortedlist properties?
p.s I know there is some possibility to use
sortedlist<object,object> srt = new sortedlist<object,object>(idictionary)
but I couldn't find the way to implement it
one solution i found for now(even though i think the combobox sort is incorrect) is by encoding the data to the sortlist
for (int i = 0; i < D.Count(); i++)
{
comboBox1.Items.Add(D[i].name);
byte[] encbuff = System.Text.Encoding.UTF8.GetBytes(D[i].name);
sortedvbcombo.Add(Convert.ToBase64String(encbuff), D[i].number);
}
is there smarter way to do it with the sortlist or with the combobox sort?

2D array to populate combobox

I am trying to populate a combobox from 2D array. I want it the first dimension to be assigned as DisplayMember values, and the second as ValueMemeber. Have been looking online, but I could not find a solution that would work for me. Below is the code that I am trying to use. This does not work.
string[,] Options = new string[3, 2]{
{"Invoice", "3"},
{"Group Invoice", "4"},
{"Group Invoice BUCKS", "5"} };
cboOption.DataSource = Options;
I have tried using a for loop and it does not work either and I get this error message: "Items collection cannot be modified when the DataSource property is set." Example below:
string[,] Options = new string[3, 2]{
{"Invoice", "3"},
{"Group Invoice", "4"},
{"Group Invoice BUCKS", "5"} };
cboOption.DisplayMember = "Text";
cboOption.ValueMember = "Key";
for (int i = 0; i < Options.GetLength(0); i++)
{
cboOption.Items.Add(new { Text = Options[i, 0], Key=Convert.ToInt16(Options[i, 1]) });
}
Can I do that? If I can could you give me an example.
Thank you
Are you sure you have tried this?.. this is a paste straight from vs and it's working
private void button1_Click(object sender, EventArgs e)
{
string[,] Options = new string[3, 2]{
{"Invoice", "3"},
{"Group Invoice", "4"},
{"Group Invoice BUCKS", "5"} };
for (int i = 0; i < Options.GetLength(0); i++)
{
cboOption.Items.Add(new { Text = Options[i, 0], Key = Convert.ToInt16(Options[i, 1]) });
}
cboOption.DisplayMember = "Text";
cboOption.ValueMember = "Key";
}
When you have a control databound, you do not add items to the control, you add them to the bound datasource. Instead of adding items to cboOption.Items, add them to the collection that your control is bound to. In your case however, you have an array. You would be better off rewriting that array into a resizable collection or datatable.
Thanks to #gmiley for the advise. After trying all the different options came up with a solution.
So I created a class Options instead of the array
public class Options
{
public string Name { get; set; }
public int Value { get; set; }
}
Then I used the code below to populate combobox
var items = new List<Options>
{
new Options() { Name="Invoice", Value=3},
new Options() { Name="Group Invoice", Value=4},
new Options() { Name="Group Invoice BUCKS", Value=5},
};
cboOption.DataSource = items;
cboOption.DisplayMember = "Name";
cboOption.ValueMember = "Value";

C# Divide the values of one list by the values of the other to produce a new list

I wish to divide the corresponding values of each list in order to produce a new list containing the divided results of each corresponding index in my two lists. Both my lists are 8 values long and are both int lists. I am currently creating two lists that are to be divided like so:
private void StartSchedule_Click(object sender, EventArgs e)
{
string ConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=F:\A2 Computing\C# Programming Project\TriHard.accdb";
string SelectQuery = "SELECT Time.AthleteID, Athlete.AthleteName, Time.EventTime, Event.EventDistance FROM Event INNER JOIN (Athlete INNER JOIN [Time] ON Athlete.[AthleteID] = Time.[AthleteID]) ON Event.[EventID] = Time.[EventID];";
OleDbConnection Connection = new OleDbConnection(ConnectionString);
OleDbCommand Command = new OleDbCommand(SelectQuery, Connection);
Command.Connection.Open();
OleDbDataReader Reader = Command.ExecuteReader(CommandBehavior.CloseConnection);
PaceCalculator pace = new PaceCalculator();
List<int> Distancelist = new List<int>();
List<int> Secondslist = new List<int>();
List<int> Pacelist = new List<int>();
while (Reader.Read())
{
pace = new PaceCalculator();
pace.Distance = (int)Reader["EventDistance"];
int DistanceInt = Convert.ToInt32(pace.Distance);
Distancelist.Add(DistanceInt);
pace = new PaceCalculator();
pace.Time = (string)Reader["EventTime"]; //Reads in EventTime
double Seconds = TimeSpan.Parse(pace.Time).TotalSeconds; //Converts the string into HH:MM:SS as a double
int SecondsInt = Convert.ToInt32(Seconds); //Converts the double into an integer, returning the seconds in the total time
Secondslist.Add(SecondsInt); //Adds the Seconds for each time to the list;
//Need to fix this currently returns just 0
var Pacelist2 = PaceCalc(Distancelist, Secondslist);
listBox3.DisplayMember = "PaceInt";
listBox3.DataSource = (Pacelist2);
}
listBox1.DisplayMember = "DistanceInt";
listBox1.DataSource = Distancelist;
listBox2.DisplayMember = "SecondsInt";
listBox2.DataSource = Secondslist;
Here is the function I am calling which attempts to divide the lists, but doesn't seem to be working:
public List<int> PaceCalc(List<int> Dlist, List<int> Slist)
{
PaceCalculator pace = new PaceCalculator();
List<int> Plist = new List<int>();
pace = new PaceCalculator();
for (int i = 0; i == Dlist.Count; i++)
{
int PaceInt = Dlist[i] / Slist[i];
Plist.Add(PaceInt);
}
return Plist;
}
I wish to display the outcomes of the division in listBox3. Am I dividing the lists correctly and how can I display it in the list box?
Your for loop is never executing because you're testing if i == Dlist.Count. It should be:
for (int i = 0;i < Dlist.Count; i++)
Alternatively, you could do this with LINQ:
public List<int> PaceCalc(List<int> Dlist, List<int> Slist)
{
return Dlist.Zip(Slist, (a, b) => a / b).ToList();
}
Couple of issues:
First you need to modify your check in for loop to i < Dlist.Count. Your current check i == Dlist.Count is wrong.
So your method would be:
public List<int> PaceCalc(List<int> Dlist, List<int> Slist)
{
List<int> Plist = new List<int>();
for (int i = 0; i < Dlist.Count; i++)
{
int PaceInt = Dlist[i] / Slist[i];
Plist.Add(PaceInt);
}
return Plist;
}
(I have removed PaceCalculator pace = new PaceCalculator();, since you don't need that at all in your method)
Second. You don't have to specify DisplayMember for ListBox3
var Pacelist2 = PaceCalc(Distancelist, Secondslist);
listBox3.DataSource = Pacelist2;
Although, the second issue will not cause any error/exception, since DisplayMember will not be found , it will use the default ToString overload and you will get the number.

Categories