I try to do that the func Form1_Load will display the city list.
I dont know how can i link the 3 functions of the cities (JerusalemData(), LondonData(), OttawaData()) to the function FillCitiesData();
The problem is that it doesnt show the list but only the streets without choosing a city. Another problem - in HouseNum_ValueChanged it doesnt show numbers and you can also type letters and not just numbers.
This is my code - I'll be happy if anyone can help me find the problem.
namespace PlanYourParty
{
public partial class Form1 : Form
{
List <City> cities;
List <string> streets;
public Form1()
{
InitializeComponent();
FillCitiesData();
}
public void FillCitiesData()
{
cities = new List<City>();
cities.Add(new City() { Code = "123", Name = "Jerusalem" });
cities.Add(new City() { Code = "456", Name = "London" });
cities.Add(new City() { Code = "789", Name = "Ottawa" });
JerusalemData();
LondonData();
OttawaData();
}
private void Form1_Load(object sender, EventArgs e)
{
FillCitiesData();
cmbCity.DataSource = cities;
cmbCity.DisplayMember = "Name";
cmbCity.ValueMember = "Code";
cmbCity.SelectedIndexChanged += cmbCity_SelectedIndexChanged;
}
public void JerusalemData()
{
streets = new List<string>();
cmbStreet.Items.Clear();
cmbStreet.Items.Add("Admond Peleg");
cmbStreet.Items.Add("Pardes");
cmbStreet.Items.Add("Nayman");
}
public void LondonData()
{
streets = new List<string>();
cmbStreet.Items.Clear();
cmbStreet.Items.Add("Oxford Street");
cmbStreet.Items.Add("Piccadilly");
cmbStreet.Items.Add("Highfield Ave");
}
public void OttawaData()
{
streets = new List<string>();
cmbStreet.Items.Clear();
cmbStreet.Items.Add("Riverside Drive");
cmbStreet.Items.Add("Ontario Highway");
cmbStreet.Items.Add("Moodie Drive");
}
private void cmbCity_SelectedIndexChanged(object sender, EventArgs e)
{
if (sender != null && sender as City != null)
{
string code;
code = (sender as City).Code;
if (code == "123")
{
JerusalemData();
}
else if (code == "456")
{
LondonData();
}
else OttawaData();
}
}
private void cmbStreet_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void domainUpDownHouseNumber_SelectedItemChanged(object sender, EventArgs e)
{
}
private void Form1_Load_1(object sender, EventArgs e)
{
}
}
First I suggest you separate your data model from the UI. Pull everything you need to define cities and streets in the City class. I have included two methods that return the cities in the example, and the streets for each city.
No need for separate methods that do the same thing, but with different data.
City.cs
public class City
{
public string Code { get; set; }
public string Name { get; set; }
public IList<string> Streets { get => GetStreets(this); }
public static List<City> GetCities()
{
var cities = new List<City>();
cities.Add(new City() { Code = "123", Name = "Jerusalem" });
cities.Add(new City() { Code = "456", Name = "London" });
cities.Add(new City() { Code = "789", Name = "Ottawa" });
return cities;
}
public static List<string> GetStreets(City city)
{
var streets = new List<string>();
if (city == null) return streets;
switch (city.Code)
{
case "123":
streets.Add("Admond Peleg");
streets.Add("Pardes");
streets.Add("Nayman");
break;
case "456":
streets.Add("Oxford Street");
streets.Add("Piccadilly");
streets.Add("Highfield Ave");
break;
case "789":
streets.Add("Riverside Drive");
streets.Add("Ontario Highway");
streets.Add("Moodie Drive");
break;
default:
throw new ArgumentException("Unknown city code.");
}
return streets;
}
}
Then write the UI such that the controls contain the lists of items as specified by the City.GetCities() and City.GetSreets() methods.
The currently selected city and street are returned by CurrentCity and CurrentStreet as well as their corresponding index in the combobox in CurrentCityIndex and CurrentStreetIndex.
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
cityComboBox.DataSource = City.GetCities();
cityComboBox.DisplayMember = nameof(CurrentCity.Name);
cityComboBox.ValueMember = nameof(CurrentCity.Code);
cityComboBox.SelectedIndexChanged += CityComboBox_SelectedIndexChanged;
cityComboBox.SelectedIndex = -1; // remove default selection of 1st item.
streetComboBox.DataSource = Array.Empty<string>();
streetComboBox.SelectedIndexChanged += StreetComboBox_SelectedIndexChanged;
}
private void CityComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
// TODO: Things when a city is selected.
streetComboBox.DataSource = CurrentCity?.Streets;
streetComboBox.SelectedIndex = -1; // remove default selection of 1st item.
UpdateLabels();
}
private void StreetComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
// TODO: Things when a street is selected.
UpdateLabels();
}
public void UpdateLabels()
{
cityInfo.Text = CurrentCityIndex >= 0 ? $"#{CurrentCity.Code} {CurrentCity.Name}" : "Please select a city.";
streetInfo.Text = CurrentStreetIndex >= 0 ? CurrentStreet : "Please select a street.";
}
public List<City> AllCities { get => cityComboBox.DataSource as List<City>; }
public List<string> AllStreets { get => streetComboBox.DataSource as List<string>; }
public int CurrentCityIndex { get => cityComboBox.SelectedIndex; }
public int CurrentStreetIndex { get => streetComboBox.SelectedIndex; }
public City CurrentCity { get => cityComboBox.SelectedItem as City; }
public string CurrentStreet { get => streetComboBox.SelectedItem as string; }
}
Screen Shots
Related
There is a way to get all items selected with the mouse in a list view when virtual mode is enabled for this winform.
Example of an working code in use, I can retrieve only one selected file for now. Not too much examples finded on the web and could be identified as duplicate but is not conclusive for me, or the answer is to simple.
private void FilesFoundList_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
try
{
if (e.ItemIndex >= 0 && e.ItemIndex < ListFilesInfos.Count)
{
try
{
var acc = ListFilesInfos[e.ItemIndex];
//with colors
e.Item = new ListViewItem(new string[] { acc.TagItem, acc.FileName, acc.FilePath.ToString() })
{ Tag = acc,
BackColor = SearchLabColor(0, Path.GetExtension(acc.FileName.ToString()), acc.FilePath.ToString(), acc.FileName.ToString()),
ForeColor = SearchLabColor(1, Path.GetExtension(acc.FileName.ToString()), acc.FilePath.ToString(), acc.FileName.ToString()),
UseItemStyleForSubItems = false
}; // Set Tag object property to our actual AccountInfo object
}
catch { this.Refresh(); }
}
}
catch
{
}
}
private void ShowItemsVirtual(List<SearchFilesInfo> infos)
{
try
{
FilesFoundList.VirtualListSize = infos.Count; // Set number of items in list view
}
catch { this.Refresh(); }
}
private void FilesFoundList_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (FilesFoundList.VirtualMode == true)
{
SelectedFiles.GlobalVar = (e.Item.SubItems[2]).Text.ToString() + (e.Item.SubItems[1]).Text.ToString();
}
}
You could abbreviate your code to:
List<multiSearchSelect> multiSearchSelect = new List<multiSearchSelect>();
private void FilesFoundList_VirtualItemsSelectionRangeChanged(object sender, ListViewVirtualItemsSelectionRangeChangedEventArgs e)
{
if (FilesFoundList.VirtualMode == true)
{
multiSearchSelect=
FilesFoundList.SelectedIndices
.Select(i=> new multiSearchSelect()
{
fileName = FilesFoundList.Items[i].SubItems[1].Text,
filePath = FilesFoundList.Items[item].SubItems[2].Text
});
}
}
class multiSearchSelect
{
public string fileName { set; get; }
public string filePath { set; get; }
}
I will post my solution that fits to my purpose. I have added ItemsSelectionRangeChanged event and get the list of file selected.
List<multiSearchSelect> multiSearchSelect = new List<multiSearchSelect>();
private void FilesFoundList_VirtualItemsSelectionRangeChanged(object sender, ListViewVirtualItemsSelectionRangeChangedEventArgs e)
{
if (FilesFoundList.VirtualMode == true)
{
multiSearchSelect.Clear();
ListView.SelectedIndexCollection col = FilesFoundList.SelectedIndices;
if (col.Count > 1)
{
foreach (int item in col)
{
multiSearchSelect.Add(new multiSearchSelect
{
fileName = FilesFoundList.Items[item].SubItems[1].Text,
filePath = FilesFoundList.Items[item].SubItems[2].Text
});
}
}
}
}
class multiSearchSelect
{
public string fileName { set; get; }
public string filePath { set; get; }
}
I have DataGridView with several cells. How to validate all cells and highlight invalidated cells?
Validation should work after filling cells.
I tried to use this way:
void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
}
But I need to set some validation rules for each fields(columns). For example, check on number or string.
You can try this code.
When We are going to edit cell('EmployeeName') it avoid from integer values.
When focus lost in selected cell Display the error Message.
this is My model
namespace WindowsFormsApplication1
{
public class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string EmployeeAddress { get; set; }
}
}
this is My code
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
List<Employee> EmployeeList = new List<Employee>();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Employee emp = new Employee();
emp.EmployeeAddress = "polonnaruwa";
emp.EmployeeId = 1;
emp.EmployeeName = "Kasun";
EmployeeList.Add(emp);
Employee emp1 = new Employee();
emp1.EmployeeAddress = "Kandy";
emp1.EmployeeId = 2;
emp1.EmployeeName = "Bimal";
EmployeeList.Add(emp1);
Employee emp2 = new Employee();
emp2.EmployeeAddress = "New Town";
emp2.EmployeeId = 3;
emp2.EmployeeName = "ASheain";
EmployeeList.Add(emp2);
dataGridView1.DataSource = EmployeeList;
}
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "EmployeeName")
{
int RowIndex = e.RowIndex;
int columnIndex = e.ColumnIndex;
if (e.Value != null)
{
string stringValue = (string)e.Value;
int val;
if (int.TryParse(stringValue, out val))
{
label1.Text = "it is integer";
dataGridView1.Rows[RowIndex].Cells[columnIndex].Value = "Please Enter String Value";
}
else
{
label1.Text = "it is not integer";
}
}
}
}
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
}
}
}
I have two forms a salaried employee and an hourly employee which has the employees details on it loading from a textfile. In my main form there is a listbox with the names of the employees, once one is clicked, i want to be able to press an edit employee details button on my main form and for the correct form to come up and I am struggling on how to do this. The code for my main form is here:
public partial class MainForm : Form
{
// The file used to store employee details
string employeesFile = "employees.txt";
// The collection used to hold the employee data
Employees employees;
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
employees = new Employees();
if (!employees.Load(employeesFile))
{
MessageBox.Show("Unable to load employees file");
}
else
{
PopulateListBox();
}
}
private void PopulateListBox()
{
listBoxEmployees.Items.Clear();
foreach (Employee employee in employees)
{
listBoxEmployees.Items.Add(employee.LastName + "," +
employee.FirstName);
}
listBoxEmployees.SelectedIndex = 0;
}
private void listBoxEmployees_DoubleClick(object sender, EventArgs e)
{ }
private void buttonEdit_Click(object sender, EventArgs e)
{
}
my load method:
{
public bool Load(string employeesFile)
{
bool status = false;
StreamReader inputFile = null;
string inputLine;
if (!File.Exists(employeesFile))
{
return false;
}
try
{
inputFile = new StreamReader(employeesFile);
if (inputFile != null)
{
inputLine = inputFile.ReadLine();
while (inputLine != null)
{
Employee employeeEntry =
EmployeeClass.NewEmployee(inputLine);
if (employeeEntry != null)
{
this.Add(employeeEntry);
}
inputLine = inputFile.ReadLine();
}
inputFile.Close();
}
status = true;
}
catch
{
}
return status;
}
}
the employees class code from the load method:
public class EmployeeClass
{
public static Employee NewEmployee(string employeeData)
{
if (employeeData.Length < 1)
{
return null;
}
switch (employeeData[0])
{
case 'S':
return new SalariedEmployee(employeeData);
case 'H':
return new HourlyEmployee(employeeData);
default:
return null;
the hourly employee form:
public partial class Hourly_Employee : Form {
HourlyEmployee _employeeEntry;
public Hourly_Employee()
{
InitializeComponent();
}
public HourlyEmployee employeeEntry
{
get
{
return _employeeEntry;
}
set
{
_employeeEntry = value;
}
}
private void Hourly_Employee_Load(object sender, EventArgs e)
{
textBoxlastName.Text = _employeeEntry.LastName;
textBoxfirstName.Text = _employeeEntry.FirstName;
textBoxaddress.Text = _employeeEntry.Address;
textBoxpostCode.Text = _employeeEntry.PostCode;
textBoxphoneNumber.Text = _employeeEntry.PhoneNumber;
dateTimePickerdateOfBirth.Text =
_employeeEntry.DateOfBirth.ToString();
textBoxhourlyPay.Text = _employeeEntry.HourlyPay.ToString();
textBoxoverTimePay.Text = _employeeEntry.OvertimePay.ToString();
}
}
and lastly my salaried employee form:
public partial class Salary_Employee : Form
{
SalariedEmployee _employeeEntry;
public SalariedEmployee employeeEntry
{
get
{
return _employeeEntry;
}
set
{
_employeeEntry = value;
}
}
private void Salary_Employee_Load(object sender, EventArgs e)
{
textBoxlastName.Text = _employeeEntry.LastName;
textBoxfirstName.Text = _employeeEntry.FirstName;
textBoxaddress.Text = _employeeEntry.Address;
textBoxpostCode.Text = _employeeEntry.PostCode;
textBoxphoneNumber.Text = _employeeEntry.PhoneNumber;
dateTimePickerdateOfBirth.Text =
_employeeEntry.DateOfBirth.ToString();
textBoxSalary.Text = _employeeEntry.Salary.ToString();
}
any help with this issue would be great!!
The trick is to add the employee objects to the listbox instead of only strings containing the employee names. This allows you to retrieve the selected employee directly from the listbox. Otherwise you would need a way to find the employee object belonging to a name.
Use the type of the selected item to determine the employee type and the employee form.
private void buttonEdit_Click(object sender, EventArgs e)
{
// Get the selected employee from the listBox.
object employee = listBoxEmployees.SelectedItem;
if (employee != null) { // An employee has been selected.
// Use the new C# 7.0 switch syntax in order to switch by employee type.
switch (employee) {
case SalariedEmployee sEmployee:
var sfrm = new Salary_Employee(); // Open the salaried employee form..
sfrm.employeeEntry = sEmployee;
sfrm.Show();
break;
case HourlyEmployee hEmployee:
var hfrm = new Hourly_Employee(); // Open the hourly employee form.
hfrm.employeeEntry = hEmployee;
hfrm.Show();
break;
}
}
}
In case you are using an older C# version you can test a type with
if (employee is SalariedEmployee) {
var frm = new Salary_Employee();;
frm.employeeEntry = (SalariedEmployee)employee;
frm.Show();
} else if (employee is HourlyEmployee) {
var frm = new Hourly_Employee();
frm.employeeEntry = (HourlyEmployee)employee;
frm.Show();
}
By default, an object's ToString method returns the name of the object's type. Enable the listbox to display the employees correctly by overriding the ToString method inherited from object in the common base class Employee.
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString()
{
return LastName + ", " + FirstName;
}
}
public partial class QuestionDragAndDropList : Form
{
private List<ListQuestions> Questions = new List<ListQuestions>();
private int i = 0;
public QuestionDragAndDropList()
{
InitializeComponent();
NextQuestion();
}
private void QuestionList()
{
Questions.Add(new ListQuestions("Question 1", new[] {//Answers}, 0));
Questions.Add(new ListQuestions("Question 2", new[] {//^}, 0));
Questions.Add(new ListQuestions("Question 3", new[] {//^}, 0));
Questions.Add(new ListQuestions("Question 4", new[] {//^}, 0));
}
private void NextQuestion()
{
if (i != 2)
{
lblQuestion.Text = Questions[i].GetQuestion();
string[] Ans = Questions[i].GetAns();
BtnA1.Text = Ans[0];
BtnA2.Text = Ans[1];
BtnA3.Text = Ans[2];
BtnA4.Text = Ans[3];
}
else
{
Questions[i].GetQuestion();
BitMap[] Ans = Questions[i].GetAnswers();
}
}
private void AnsCheck(int Answer)
{
if (Answer < Questions.Count)
{
WelcomeYear11.Userfiling.IncreaseS();
}
i++;
if (i != Questions.Count)
{
NextQuestion();
}
else
{
do something.
}
}
private void GrabLabel(object sender, MouseEventArgs e)
{
Label selectedLbl = (Label)sender;
selectedLbl.DoDragDrop(selectedLbl.Text, DragDropEffects.Copy);
}
private void AllowDragDrop(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Copy;
}
private void PBox1DragDrop(object sender, DragEventArgs e)
{
string result = e.Data.GetData(DataFormats.Text).ToString();
if (result == "9")
{
lblA1.Visible = false;
PboxA1.Visible = false;
}
}
private void PBox2DragDrop(object sender, DragEventArgs e)
{
string result = e.Data.GetData(DataFormats.Text).ToString();
if (result == "30")
{
LblA2.Visible = false;
PBoxA2.Visible = false;
}
}
private void PBox3DragDrop(object sender, DragEventArgs e)
{
string result = e.Data.GetData(DataFormats.Text).ToString();
if (result == "5")
{
LblA3.Visible = false;
PBoxA3.Visible = false;
}
}
private void PBox4DragDrop(object sender, DragEventArgs e)
{
string result = e.Data.GetData(DataFormats.Text).ToString();
if (result == "18")
{
LblA3.Visible = false;
PBoxA3.Visible = false;
}
}
}
So using this code, how am I able to not only have it set to generate forms with button questions but also with drag/drop, checkboxes, etc...
The ListClass used in the sample is:
class ListQuestions
{
private string Questions;
private Bitmap[] Answers; private string[] Ans; //First is for Picbox questions. Second is for button questions.
private int PosOfAns;
public ListQuestions(string questions, Bitmap[] answers, int posOfAns)
{
Questions = questions;
Answers = answers;
PosOfAns = posOfAns;
}
public ListQuestions(string questions, string[] ans, int posOfAns)
{
Questions = questions;
Ans = ans;
PosOfAns = posOfAns;
}
public string GetQuestion()
{
return Questions;
}
public string[] GetAns()
{
return Ans;
}
public Bitmap[] GetAnswers()
{
return Answers;
}
public int GetPosOfAns()
{
return PosOfAns;
}
}
Any help is much appreciated :).
I think you're after this
using System.Collections.Generic;
Bitmap[] bm = { new Bitmap(1, 1) };//just had to make one to use in the ListQuestions method overload
List<ListQuestions> thelist = new List<ListQuestions>();
thelist.Add(new ListQuestions("", bm, 1));
Basically, you create your class, then you make a list of your class
List<ListQuestions> thelist = new List<ListQuestions>();
Then you can manipulate your list
thelist.Add(new ListQuestions("", bm, 1));
But since your class properties are all private, none of them are accessible outside of your class. So after you have added items to your List<>, you can't really access any of them. For example, this won't work until your properties are public.
string question = thelist[0].Questions;
Here's a working sample
using System.Collections.Generic;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
List<myclass> mylist = new List<myclass>();
mylist = Fillmylist(mylist);
this.Controls.Add(mylist[0].chckbx_Recurse);
this.Controls.Add(mylist[0].txtbx_pwd);
this.Controls.Add(mylist[0].txtbx_usrname);
}
private List<myclass> Fillmylist(List<myclass> incominglist)
{
TextBox tb = new TextBox();
tb.Name = "txtbx_usr";
tb.SetBounds(20, 20, 50, 10);
TextBox tbp = new TextBox();
tbp.Name = "txtbx_pwd";
tbp.SetBounds(20,50, 50, 10);
CheckBox cb = new CheckBox();
cb.Name = "chkbx_recurse";
cb.SetBounds(20, 80, 20, 20);
incominglist.Add(new myclass { txtbx_usrname = tb, txtbx_pwd = tbp, chckbx_Recurse = cb });
return incominglist;
}
}
class myclass
{
public TextBox txtbx_usrname { get; set; }
public TextBox txtbx_pwd { get; set; }
public CheckBox chckbx_Recurse { get; set; }
}
}
I have three classes, and the code is provided below.
Network - Add and Remove Phone, Process Calls. Phone1 and Phone2 can call each other when added to the network.
But I am having an issue when I am connecting both the phone to the network and trying to call phone1 to phone2; it is keeping giving me "receiver busy". I have tried to do a little debugging and read the status of phone2 when calling from phone1, but it returns an empty string (which should actually return "A", when it is added to the network as I am setting its value to "A").
public partial class network : Form
{
phone1 p1 = new phone1();
phone2 p2 = new phone2();
public network()
{
InitializeComponent();
}
public Boolean numberValidator(int number)
{
Boolean exist = false;
if (comboBox2.Items.Equals(number))
{
exist = true;
}
return exist;
}
public void processCall(int rNumber)
{
if (!numberValidator(rNumber))
{
p1.TextBox1.Clear();
p1.TextBox1.Text = "Not connected";
}
else
{
p1.TextBox1.Clear();
p1.TextBox1.Text = "Call in progress";
p2.receiveCall(1);
p1.setStatus("Busy");
/*
if (p2.btnCallPressStatus())
{
p1.TextBox1.Clear();
p1.TextBox1.Text = "Call initiated";
}*/
}
}
private void button1_Click(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == 0)
{
p1.Show();
comboBox2.Items.Add(1);
p1.setStatus("A");
}
if (comboBox1.SelectedIndex == 1)
{
p2.Show();
comboBox2.Items.Add(2);
p2.setStatus("A");
}
}
}
----------Phone1 Class---------
public partial class phone1 : Form
{
public phone1()
{
InitializeComponent();
}
string status;
public void setStatus(string Status)
{
status = Status;
}
public string returnStatus()
{
return status;
}
public void receiveCall(int callerNumber)
{
setStatus("Busy");
btnCall.Text = "Answer";
textBox1.Text = "Phone " + callerNumber + " Calling.";
}
public void makeCall(int number)
{
phone2 p2 = new phone2();
network net = new network();
MessageBox.Show(p2.returnStatus()); // this line not returing status of phone2
if (p2.returnStatus() == "A")
{
net.processCall(number);
}
else
{
textBox1.Text = "Receiver Busy";
}
}
public TextBox TextBox1
{
get
{
return textBox1;
}
}
private void btnCall_Click(object sender, EventArgs e)
{
string number = textBox1.Text;
int numberInt = Convert.ToInt16(number);
makeCall(numberInt);
}
string phoneNo = "";
private void btn2_Click(object sender, EventArgs e)
{
phoneNo = phoneNo + btn2.Text;
textBox1.Text = phoneNo;
}
}
-------------phone2 Class--------------
public partial class phone2 : phone1
{
public phone2()
{
InitializeComponent();
}
}
The routine makeCall is creating a new instance of phone2 and calling returnStatus next. The problem is that the string "status" is not Being initialized with any value when p2 is created, so, the returno value will never be "A" and you will always fail the test.