I'm trying to learn the basics of C# and decided to make a simple windows form to demonstrate the Dictionary class, but when I start my program, the Combo-/ListBox controls stay blank, although I loaded some data to them. Hope you could help me out with this.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace ClassDictionaryExample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Dictionary<string, string[]> CountryList = new Dictionary<string, string[]>();
private void Form1_Load(object sender, EventArgs e)
{
CountryList["Bulgaria"] = new string[] { "Sofia University St Kliment Ohridski", "Technical University of Sofia",
"Plovdiv University Paisii Hilendarski" };
CountryList["Romania"] = new string[] { "Alexandru Ioan Cuza University", "Babes-Bolyai University",
"University of Bucharest" };
CountryList["Serbia"] = new string[] { "University of Belgrade", "University of Novi Sad", "University of Niš" };
foreach (var CountryKey in CountryList.Keys)
{
comboBoxCountry.Items.Add(CountryKey);
}
comboBoxCountry.SelectedIndex = 0;
}
private void comboBoxCountry_SelectedIndexChanged(object sender, EventArgs e)
{
string selectedCountry = comboBoxCountry.SelectedItem.ToString();
if (comboBoxCountry.SelectedIndex == 0)
listBoxUniversities.Items.Clear();
else
{
listBoxUniversities.Items.Clear();
listBoxUniversities.Items.AddRange(CountryList[selectedCountry]);
}
}
}
}
I tried to reproduce your problem but could not. You need to keep in mind that you have to assign 2 events to your code. One on FormLoaded and other on ComboboxSelectionChanged.
I have reduced your code to show universities when selected Index is zero.
public Form1()
{
InitializeComponent();
this.Load += Form1_Load;
comboBoxCountry.SelectedIndexChanged += comboBoxCountry_SelectedIndexChanged;
}
private Dictionary<string, string[]> _countryList;
public Dictionary<string, string[]> CountryList
{
get
{
if (_countryList == null)
{
_countryList = new Dictionary<string, string[]>();
_countryList["Bulgaria"] = new string[] { "Sofia University St Kliment Ohridski", "Technical University of Sofia", "Plovdiv University Paisii Hilendarski" };
_countryList["Romania"] = new string[] { "Alexandru Ioan Cuza University", "Babes-Bolyai University", "University of Bucharest" };
_countryList["Serbia"] = new string[] { "University of Belgrade", "University of Novi Sad", "University of Niš" };
}
return _countryList;
}
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (var CountryKey in CountryList.Keys)
comboBoxCountry.Items.Add(CountryKey);
comboBoxCountry.SelectedIndex = 0;
}
private void comboBoxCountry_SelectedIndexChanged(object sender, EventArgs e)
{
string selectedCountry = comboBoxCountry.SelectedItem.ToString();
listBoxUniversities.Items.Clear();
listBoxUniversities.Items.AddRange(CountryList[selectedCountry]);
}
Related
I'm working on a project that requires me to create items in one form, put them in a List in another and them insert them for display on a list view on a third. I have a custom event set up to add the items to their appropriate place but it doesn't work and I can't figure out why.
My UserInputForm is where the info is put in. I have a get/set method to pull the data from the fields. The declared EventHandler is in this form.
public partial class UserInputForm : Form
{
public UserInputForm()
{
InitializeComponent();
}
MainForm main;
public EventHandler AddNewItem;
public Items EachItem
{
get
{
Items newItem = new Items();
newItem.Name = nameBox.Text;
newItem.Month = monthBox.Text;
newItem.Day = dayBox.Value;
newItem.Senior = seniorCheckBox.Checked;
newItem.ImageIndex = monthBox.SelectedIndex;
return newItem;
}
set
{
nameBox.Text = value.Name;
monthBox.Text = value.Month;
dayBox.Value = value.Day;
seniorCheckBox.Checked = value.Senior;
}
}
private void AddItem (object sender, EventArgs e)
{
if (main == null)
{
main = new MainForm();
}
AddNewItem += main.AddNewItemHandler;
if (AddNewItem != null)
{
AddNewItem(this, new EventArgs());
}
EachItem = new Items();
}
}
In the Main, I have the event that adds the item to the list, calls a method to display the # of items in the list, and calls a method in the ListView Form to add it there.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
List<Items> inputItems = new List<Items>();
UserInputForm newInput;
ListView list;
public void AddNewItemHandler(object sender, EventArgs e)
{
newInput = sender as UserInputForm;
Items newItem = newInput.EachItem;
inputItems.Add(newItem);
if (list == null)
{
list = new ListView();
}
list.AddToListView(newItem);
TotalInList();
}
private void OpenInputForm(object sender, EventArgs e)
{
newInput = new UserInputForm();
if (newInput.IsDisposed == true)
{
newInput = new UserInputForm();
}
newInput.Show();
OpenInputNum();
newInput.FormClosed += InputFormClosed;
}
private void OpenListView(object sender, EventArgs e)
{
if (Application.OpenForms.OfType<ListView>().Count<ListView>() == 1)
{
Application.OpenForms.OfType<ListView>().First().Close();
displayList.Checked = false;
}
else
{
if (list == null)
{
list = new ListView();
}
if (list.IsDisposed == true)
{
list = new ListView();
}
list.Show();
list.Load += ListOpened;
}
}
private void OpenInputNum()
{
string inputNum = $"{Application.OpenForms.OfType<UserInputForm>().Count<UserInputForm>()}";
openInputNumBox.Text = inputNum;
}
private void ListOpened(object sender, EventArgs e)
{
if (list == null)
{
list = new ListView();
}
if (list.IsDisposed == true)
{
list = new ListView();
}
list.AddToNewListView(inputItems);
}
public void TotalInList()
{
string listNum = $"{inputItems.Count()}";
itemListNumBox.Text = listNum;
}
}
The ListView Form has a method that adds all items at once when its opened or a single item when its already open. It changes the item to a ListViewItem and adds it to the list.
public partial class ListView : Form
{
public ListView()
{
InitializeComponent();
}
//list for listview
List<Items> toView;
public void AddToNewListView(List<Items> toListView)
{
toView = toListView;
ListViewItem addItem = new ListViewItem();
foreach (Items item in toView)
{
addItem.Text = item.ToString();
addItem.ImageIndex = item.ImageIndex;
addItem.Tag = item;
itemListView.Items.Add(addItem);
}
}
public void AddToListView(Items newItem)
{
ListViewItem addItem = new ListViewItem();
addItem.Text = newItem.ToString();
addItem.ImageIndex = newItem.ImageIndex;
addItem.Tag = newItem;
itemListView.Items.Add(addItem);
}
}
The problems I'm having are:
Though I follow the data and though it all seems to be there when needed, my ListView will not populate and neither will the count for the number of items in the main. Is there something wrong with my code?
I am working on a project where I read some serial data from a board, and try to show it on a graph plot.
So far I have managed to implement the Oxyplot inside my application.
But I am confused how to update the plot on each new data coming from the serial port?
Here is my code in a simplified version
using OxyPlot;
namespace Motor
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ComPort.DataReceived += new
System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived_1);
plot1.Model = GridLinesHorizontal();
}
public static PlotModel GridLinesHorizontal()
{
var plotModel = new PlotModel();
plotModel.Title = "Horizontal";
var linearAxis1 = new LinearAxis();
linearAxis1.MajorGridlineStyle = LineStyle.Solid;
linearAxis1.MinorGridlineStyle = LineStyle.Dot;
linearAxis1.Maximum = 5;
linearAxis1.Minimum = -5;
plotModel.Axes.Add(linearAxis1);
return plotModel;
}
private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
{
InputData = ComPort.ReadLine();
if (InputData != String.Empty)
{
this.BeginInvoke(new SetTextCallback(SetText), new object[] { InputData });
}
}
private void SetText(string text)
{
dVal = double.Parse(text, CultureInfo.InvariantCulture); // convert to double
///// HERE I WANT TO UPDATE THE PLOT with dval
}
}
}
Not sure if that's the best way of doing it but something like this should work:
using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Series;
namespace Motor
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ComPort.DataReceived += new
System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived_1);
plot1.Model = GridLinesHorizontal();
//create new LineSeries and add it to the PlotView
Line1 = new LineSeries
{
Title = "Test Series",
Color = OxyColors.Red,
TextColor = OxyColors.Red,
BrokenLineColor = OxyColors.Red
};
plot1.Model.Series.Add(Line1);
}
LineSeries Line1; // declare Line1 as global
public static PlotModel GridLinesHorizontal()
{
var plotModel = new PlotModel();
plotModel.Title = "Horizontal";
var linearAxis1 = new LinearAxis();
linearAxis1.MajorGridlineStyle = LineStyle.Solid;
linearAxis1.MinorGridlineStyle = LineStyle.Dot;
linearAxis1.Maximum = 5;
linearAxis1.Minimum = -5;
plotModel.Axes.Add(linearAxis1);
return plotModel;
}
private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
{
InputData = ComPort.ReadLine();
if (InputData != String.Empty)
{
this.BeginInvoke(new SetTextCallback(SetText), new object[] { InputData });
}
}
int plotIndex = 0;
private void SetText(string text)
{
dVal = double.Parse(text, CultureInfo.InvariantCulture); // convert to double
///// plotIndex is the x value of the new point, not sure if OxyPlot offers an auto increment option
Line1.Points.Add(new DataPoint(plotIndex, dVal));
plotIndex++;
plot1.Invalidate();
}
}
}
When I go to run the program it is empty, no data displayed
namespace _0000003
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
soulpets = new ListView();
ListViewItem lvi6001 = soulpets.Items.Add("6001");
lvi6001.SubItems.Add("Tough Ent, Rare");
ListViewItem lvi6004 = soulpets.Items.Add("6004");
lvi6004.SubItems.Add("Stone Fist Ent, Rare");
ListViewItem lvi6007 = soulpets.Items.Add("6007");
lvi6007.SubItems.Add("Healing Ent,Rare");
Controls.Add(soulpets);
soulpets = new ListView();
should be soulpets.Items.Clear();
You probably want:
add a listview via the designer with the name soulpets
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
fillListViewSoulpets();
}
private void fillListViewSoulpets()
{
soulpets.Items.Clear(); //it should already be empty
soulpets.Items.Add(
new ListViewItem({ "Tough", "Ent", "Rare" }),
new ListViewItem({ "Stone", "Fist", "Ent", "Rare" }),
new ListViewItem({ "Healing", "Ent", "Rare" })
);
}
}
I am having this very strange problem where i am creating a list of some objects in one class then trying to access it in another class but it's coming empty in other class:
My first class where i am populating the list:
namespace dragdrop
{
struct BR
{
private string var;
public string Var
{
get { return var; }
set { var = value; }
}
private string equalsTo;
public string EqualsTo
{
get { return equalsTo; }
set { equalsTo = value; }
}
private string output;
public string Output
{
get { return output; }
set { output = value; }
}
private string els;
public string Els
{
get { return els; }
set { els = value; }
}
private string elsOutput;
public string ElsOutput
{
get { return elsOutput; }
set { elsOutput = value; }
}
}
public partial class Form1 : Form
{
//******************
private List<BR> list = new List<BR>(); //This is the list!
//******************
internal List<BR> List
{
get { return list; }
set { list = value; }
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] vars = new string[] { "Name", "Gender", "Age", "Address", "email" };
comboBox1.DataSource = vars;
}
private void button1_Click(object sender, EventArgs e)
{
BR b = new BR();
b.Var = comboBox1.SelectedItem.ToString();
b.EqualsTo = textBox1.Text;
b.Output = textBox2.Text;
list.Add(b);
//*****************
textBox1.Text = List.Count.ToString(); //This gives the correct count value!
//*****************
//this.Close();
}
}
}
I am accessing it in second class like:
namespace dragdrop
{
public partial class Ribbon1
{
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
}
private void button1_Click(object sender, RibbonControlEventArgs e)
{
Form1 form = new Form1();
List<BR> l = form.List; ;
//*******************
MessageBox.Show(form.List.Count.ToString()); //This strangely gives count 0!
//*******************
}
}
}
I have even tried making everything public in first class but no matter what i do, im always getting empty list in second class.
The is no relation what-so-ever between Form1 and Ribbon1, how can one then access an instance of the other?
With this:
Form1 form = new Form1(); // new instance of Form1
List<BR> l = form.List; ; // of course the list is empty in a new instance!
you can never access values from another instance of Form1.
Since I have no idea how your classes are connected I cannot give you more advice than have a look at this good overview of OO-relationships. You have to connect them somehow for it to work, I would very much recommend composition // aggregation (same thing, different schools).
All i needed to do was make the list a static member in class one, that solved the issue of having different value when i tried to create a new instance of Form1 in Ribbon1 class.
private static List<BR> list = new List<BR>();
I have a ListBox named lsbEntities. I want to filter it's items based on some selected radio button.
The code below is kind of pseudo, is their a better approach?
private List<string> _listBoxItemsToFilter;
private Thread tFilterEntityList;
enum EntityType
{
Vehicle,
Facility
}
private void FilterEntityList(EntityType entityType)
{
_listBoxItemsToFilter = new List<string>();
Dictionary<string,string> entitiesAndClassTypes;
List<string> listBoxItems = new List<string>();
for(int i = 0; i < lsbEntities.Count; i++)
{
//object listItem = lsbEntities.Items[i];
listBoxItems.Add(lsbEntities[i].ToString());
}
// get associated types
entityClassTypes = _controlFacade.GetClassTypes(listBoxItems);
foreach (KeyValuePair<string,string>
entityAndClass in entitiesAndClassTypes)
{
classType = entityAndClass.Value;
if(classType != entityType)
{
_listBoxItemsToFilter.Add(entityAndClass.Key);
}
}
RemoveFilterFromEntityListBox();
AddFilterToEntityListBox();
}
private void AddFilterToEntityListBox()
{
// DELEGATE NEEDED TO MODIFY LISTBOX FROM THREAD
foreach(string listBoxItem in _listBoxItemsToFilter)
{
if(lsbEntities.Contains(listBoxItem)
{
// REMOVE WITH DELEGATE
}
}
}
private void RemoveFilterFromEntityListBox()
{
// DELEGATE NEEDED TO MODIFY LISTBOX FROM THREAD
if(_listBoxItemsToFilter != null)
{
foreach(string listBoxItem in _listBoxItemsToFilter)
{
if(!lsbEntities.Contains(listBoxItem)
{
// REMOVE WITH DELEGATE
}
}
}
}
// EXAMPLE CALL WHEN CLICKING RADIO-BUTTON
private void rbVehicles_CheckedChanged(object sender, EventArgs e)
{
switch (rbVehicles.Checked)
{
case (true):
{
object entityType = (object)EntityType.Vehicle;
tFilterEntityList = new Thread(FilterEntityList(entityType));
tFilterEntityList.IsBackground = true;
tFilterEntityList.Start();
//FilterEntityList(EntityType.Vehicle);
break;
}
}
}
I have only included an example of selecting to filter everything but VehicleS. The same approach would be used for the Facility class, where the thread would be re-instantiated.
Here is a simple example showing one way to filter items in a ListBox. This could be improved by using a ListView or DataGridView in VirtualMode. It is very unclear to me what you are trying to do, so if this is not helpful I will remove it.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
public class Form1 : Form
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
List<Entity> items = new List<Entity>()
{
new Entity(EntityType.Vehicle, "Car"),
new Entity(EntityType.Vehicle, "Aeroplane"),
new Entity(EntityType.Vehicle, "Truck"),
new Entity(EntityType.Vehicle, "Bus"),
new Entity(EntityType.Facility, "Garage"),
new Entity(EntityType.Facility, "House"),
new Entity(EntityType.Facility, "Shack"),
};
ListBox listBox;
ComboBox comboBox;
public Form1()
{
Text = "Filtering Demo";
ClientSize = new Size(500, 320);
Controls.Add(listBox = new ListBox
{
Location = new Point(10, 10),
Size = new Size(200, 300),
});
Controls.Add(comboBox = new ComboBox
{
Location = new Point(230, 10),
DropDownStyle = ComboBoxStyle.DropDownList,
Items = { "All", EntityType.Vehicle, EntityType.Facility },
SelectedIndex = 0,
});
comboBox.SelectedIndexChanged += UpdateFilter;
UpdateFilter(comboBox, EventArgs.Empty);
}
void UpdateFilter(object sender, EventArgs e)
{
var filtered = items.Where((i) => comboBox.SelectedItem is string || (EntityType)comboBox.SelectedItem == i.EntityType);
listBox.DataSource = new BindingSource(filtered, "");
}
}
enum EntityType { Vehicle, Facility, }
class Entity : INotifyPropertyChanged
{
public string Name { get; private set; }
public EntityType EntityType { get; private set; }
public Entity(EntityType entityType, string name) { EntityType = entityType; Name = name; }
public override string ToString() { return Name ?? String.Empty; }
// Implementing INotifyPropertyChanged to eliminate (caught) BindingSource exceptions
public event PropertyChangedEventHandler PropertyChanged;
}