Update a value in treeListView in objectListView - c#

I have built a treeListView:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TreeListViewTest1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.treeListView1.CanExpandGetter = delegate(object x)
{
return true;
};
this.treeListView1.ChildrenGetter = delegate(object x)
{
Contract contract = x as Contract;
return contrat.Children;
};
column1.AspectGetter = delegate(object x)
{
if(x is Contract)
{
return ((Contract)x).Name;
}
else
{
return " ";
}
};
column2.AspectGetter = delegate(object x)
{
if(x is Contract)
{
return ((Contract)x).Value;
}
else
{
Double d = (Double)x;
return d.ToString();
}
};
this.treeListView1.AddObject(new Contract("A", 1));
}
private void treeListView1_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
public class Contract
{
public string Name { get; set;}
public Double Value { get; set; }
public List<Double> Children {get; set;}
public Contract(string name, Double value)
{
Name = name;
Value = value;
Children = new List<Double>();
Children.Add(2);
Children.Add(3);
}
}
}
It gives this output:
Name Value
A 1
2
3
How do I update the values of column2 ("Value") of the parent and the children from within an event? (increasing each value by of the parent and the children.)
private void button1_Click(object sender, EventArgs e)
{
}
I do not understand if I have to use the AspectGetter again or can i modify just the values in column2 somehow and then refreshObjects().

I do not understand if I have to use the AspectGetter again or can i modify just the values in column2 somehow and then refreshObjects().
No, you should just manipulate the underlying model object and call treeListView1.RefreshObject(myObject); for example, where myObject should be a Contract in you case. This will refresh the contents of the respective rows.
I don't know what your button1_Click() is supposed to do, but you obviously require a reference of the object you want to refresh. This could be the currently selected object for example (treeListView.SelectedObject). If you tell what you want to do, I may be able to give you more information.

Related

Where should I put my variables in a Windows Forms Application without having to make it global? [duplicate]

This question already has answers here:
Model-View-Presenter in WinForms
(3 answers)
How to Structure a C# WinForms Model-View-Presenter (Passive View) Program?
(2 answers)
Closed 2 years ago.
I have a predicament! I don't know where I should put my variables in a C# Windows Forms Application. For example, in my WFA project I have a list of my own datatype object called "Item" and at the moment I've had to make it global, however, I understand global isn't the best of practises. Because I come from a C++ background I'd always create my variables in int main() and pass them to functions where needed. I honestly can't find an answer anywhere. Many thanks to anyone who can assist me.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Sales_Calculator
{
public partial class Form1 : Form
{
//Should my list<Item> go here or is there a better place for it?
List<Item> objItems = new List<Item>();
public Form1()
{
InitializeComponent();
}
public class Item
{
private string m_sItemName;
private double m_dItemPrice;
private int m_iQuantitySold;
public Item(string sItemName, double dItemPrice, int iQuantitySold)
{
m_sItemName = sItemName;
m_dItemPrice = dItemPrice;
m_iQuantitySold = iQuantitySold;
}
public string Name
{
get { return m_sItemName; }
set { m_sItemName = value; }
}
public int QuantitySold
{
get { return m_iQuantitySold; }
set { m_iQuantitySold = value; }
}
public double Price
{
get { return m_dItemPrice; }
set { m_dItemPrice = value; }
}
}
bool DoesItemNameExist(string sName)
{
return (objItems.Find(delegate (Item objItem){return sName == objItem.Name;}) != null) ? true : false;
}
private Item HighestSellingItem()
{
int MaxQuantitySold = objItems.Max(objItem => objItem.QuantitySold);
return objItems.Find(delegate (Item objItem) {
return objItem.QuantitySold == MaxQuantitySold;
});
}
private double Average()
{
int iTotal = 0;
objItems.ForEach(delegate (Item objItem)
{
iTotal += objItem.QuantitySold;
});
double dAverage = iTotal / objItems.Count;
return dAverage;
}
private void label1_Click(object sender, EventArgs e)
{
}
private void AddToDataGridView(object sender)
{
dgvItems.Rows.Add(objItems.Count, objItems.Last().Name, objItems.Last().QuantitySold, objItems.Last().Price);
}
void ClearTextBoxes()
{
txtItemName.Clear();
txtItemPrice.Clear();
txtQuantitySold.Clear();
}
void AddItemToList()
{
string sItemName = "";
if (DoesItemNameExist(sItemName = Convert.ToString(txtItemName.Text)))
{
MessageBox.Show("You can't have that name, it already exists!");
txtItemName.Clear();
return;
}
double dItemPrice = Convert.ToDouble(txtItemPrice.Text);
int iQuantitySold = Convert.ToInt32(txtQuantitySold.Text);
Item objItem = new Item(sItemName, dItemPrice, iQuantitySold);
objItems.Add(objItem);
MessageBox.Show("You have added an item!");
ClearTextBoxes();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
AddItemToList();
AddToDataGridView(sender);
lblAverageQuantitySold.Text = Average().ToString();
lblExistingItems.Text = objItems.Count.ToString();
}
catch (Exception ex)
{
MessageBox.Show("You have inputted incorrectly!", "Invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
dvgHighestSellingItem.Rows.Clear();
dvgHighestSellingItem.Rows.Add(HighestSellingItem().Name);
}
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
}
}
}

how to separate the selected items in a checkbox?

I have two forms in WFA C#.
FORM1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication8
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
if (checkBox1.Checked == true)
{
f2.intr = checkBox1.Text;
}
if (checkBox2.Checked == true)
{
f2.intr2 = checkBox2.Text;
}
if (checkBox3.Checked == true)
{
f2.intr3 = checkBox3.Text;
}
if (checkBox4.Checked == true)
{
f2.intr4 = checkBox4.Text;
}
if (checkBox5.Checked == true)
{
f2.intr5 = checkBox5.Text;
}
f2.ShowDialog();
}
}
}
FORM2:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication8
{
public partial class Form2 : Form
{
public string gen, intr, intr2, intr3, intr4, intr5;
public string interest
{
get { return intr; }
set { intr = value; }
}
public string interest2
{
get { return intr2; }
set { intr2 = value; }
}
public string interest3
{
get { return intr3; }
set { intr3 = value; }
}
public string interest4
{
get { return intr4; }
set { intr4 = value; }
}
public string interest5
{
get { return intr5; }
set { intr5 = value; }
}
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
label1.Text = "Interests: " + interest + "\n" + interest2 + "\n" + interest3 + "\n" + interest4 + "\n" + interest5;
}
}
}
I have 5 checkboxes inside a groupbox. This outputs the selected items to label1. The output looks like this when I check all the checkboxes:
art
science
math
history
sports
and whenever I check boxes randomly for example i'll check the art and history. The output is like this:
art
history
it leaves two spaces.
In the design of form1 there are the checkbox1,checkbox2,checkbox3,checkbox4,checkbox5 inside a groupbox.
In the design of form2 there is only label1.
How can I separate the selected items by a comma in one line?
I'm new to c# helpp.
You could put all the interests in an array:
string[] interests = { interest, interest2, interest3, interest4, interest5 };
Then you could remove the non-selected ones:
string[] selectedInterests = interests.Where(str => !String.IsNullOrEmpty(str)).ToArray();
At the end you can join them into a single string:
label1.Text = String.Join(", ", selectedInterests);

Checking a Property of an Object In a Queue

I need to compare a name of an object (test) with the name of a test that has been placed into a queue. The logic I have is to use a foreach loop so that for each test in the queue I can compare the name that the user provides with the name on each test until it finds a match (in which it will tell the user the score they made on the test in a message box).
The code in the snippet is incomplete; using submittedTests with a getter doesn't work (doesn't give me an option to do so in intellisense).
This takes place in the btnFindTest_Click method. This is the code that I have so far:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ConsoleApplication1
{
public partial class Form1 : Form
{
//Stack and Queue calls
Queue submittedTest = new Queue();
Stack outForChecking = new Stack();
public Form1()
{
InitializeComponent();
}
private void btnSubmitTest_Click(object sender, EventArgs e)
{
//generates a random test score
Random rdm = new Random();
int testScore = rdm.Next(0, 100);
string score = testScore.ToString();
//assigns user input to a variable
string name = txtName.Text;
//Generate a new test that passes in
Test tests = new Test(name, score);
//shows the user the name they just enetered
label3.Text = String.Format("{0}", name);
//adds submitted test to the queue, then displays that test in a list box
submittedTest.Enqueue(tests);
listSubTests.Items.Add(new Test(name, score));
//Clears input box for next user input
txtName.Clear();
}
private void btnFindTest_Click(object sender, EventArgs e)
{
string compareName = "";
string tempName = txtName.Text;
foreach (Test tests in submittedTest)
{
if (compareName == tempName)
{
System.Windows.Forms.MessageBox.Show("Your score was --");
}
}
}
public void txtName_TextChanged(object sender, EventArgs e)
{
}
private void txtScore_TextChanged(object sender, EventArgs e)
{
}
private void btnExit_Click(object sender, EventArgs e)
{
Close();
}
}
}
And the test object is defined in it's own class here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Test
{
private string name;
private string score;
public string Name
{
get { return name; }
set { name = value; }
}
public string Score
{
get { return score; }
set { score = value; }
}
public Test(string name, string score)
{
this.name = name;
this.score = score;
}
public override string ToString()
{
return (String.Format("{0} {1} ", name, score));
}
}
}
I'm reletively new to C# and this project is for school, so if I'm far off, please let me know!
Based on your example, you may have forgotten to use the object:
foreach (Test tests in submittedTest)
{
if (tests.Name == tempName)
{
System.Windows.Forms.MessageBox.Show("Your score was --");
}
}

C# delegates problem

I am getting the following error from my C# Windows Application:
Error 1 No overload for 'CreateLabelInPanel' matches delegate 'WorksOrderStore.ProcessDbConnDetailsDelegate' H:\c\WorksOrderFactory\WorksOrderFactory\WorksOrderClient.cs 43 39 WorksOrderFactory
I have 3 .cs files that essentially:
Opens a windows
Has an option for the users to connect to a db
When that is selected, the system will go off and connect to the db, and load some data in (just test data for now)
Then using a delegate, the system should do soemthing, which for testing will be to create a label. However I haven't coded this part yet.
But I can't build until I get this error sorted.
The 3 fiels are called:
WorksOrderClient.cs (which is the MAIN)
WorksOrderStore.cs
LoginBox.cs
Here's the code for each file:
WorksOrderClient.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WorksOrderStore;
namespace WorksOrderFactory
{
using WorksOrderStore;
public partial class WorksOrderClient : Form
{
LoginBox lb = new LoginBox();
private static WorksOrderDB wodb = new WorksOrderDB();
private static int num_conns = 0;
public WorksOrderClient()
{
InitializeComponent();
}
private void connectToADBToolStripMenuItem_Click(object sender, EventArgs e)
{
lb.ShowDialog();
lb.Visible = true;
}
public static bool createDBConnDetObj(string username, string password, string database)
{
// increase the number of connections
num_conns = num_conns + 1;
// create the connection object
wodb.AddDbConnDetails(username, password, database, num_conns);
// create a new delegate object associated with the static
// method WorksOrderClient.createLabelInPanel
wodb.ProcessDbConnDetails(new ProcessDbConnDetailsDelegate(CreateLabelInPanel));
return true;
}
static void CreateLabelInPanel(DbConnDetails dbcd)
{
Console.Write("hellO");
string tmp = (string)dbcd.username;
//Console.Write(tmp);
}
private void WorksOrderClient_Load(object sender, EventArgs e)
{
}
}
}
WorksOrderStore.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WorksOrderFactory;
namespace WorksOrderStore
{
using System.Collections;
// Describes a book in the book list:
public struct WorksOrder
{
public string contractor_code { get; set; } // contractor ID
public string email_address { get; set; } // contractors email address
public string date_issued { get; set; } // date the works order was issued
public string wo_ref { get; set; } // works order ref
public string status { get; set; } // status ... not used
public job_status js { get; set; } // status of this worksorder within this system
public WorksOrder(string contractor_code, string email_address, string date_issued, string wo_ref) : this()
{
this.contractor_code = contractor_code;
this.email_address = email_address;
this.date_issued = date_issued;
this.wo_ref = wo_ref;
this.js = job_status.Pending;
}
}
// Declare a delegate type for processing a WorksOrder:
//public delegate void ProcessWorksOrderDelegate(WorksOrder worksorder);
// Maintains a worksorder database.
public class WorksOrderDB
{
// List of all worksorders in the database:
ArrayList list = new ArrayList();
// Add a worksorder to the database:
public void AddWorksOrder(string contractor_code, string email_address, string date_issued, string wo_ref)
{
list.Add(new WorksOrder(contractor_code, email_address, date_issued, wo_ref));
}
// Call a passed-in delegate on each pending works order to process it:
/*public void ProcessPendingWorksOrders(ProcessWorksOrderDelegate processWorksOrder)
{
foreach (WorksOrder wo in list)
{
if (wo.js.Equals(job_status.Pending))
// Calling the delegate:
processWorksOrder(wo);
}
}*/
// Add a DbConnDetails to the database:
public void AddDbConnDetails(string username, string password, string database, int conn_num)
{
list.Add(new DbConnDetails(username, password, database, conn_num));
}
// Call a passed-in delegate on each dbconndet to process it:
public void ProcessDbConnDetails(ProcessDbConnDetailsDelegate processDBConnDetails)
{
foreach (DbConnDetails wo in list)
{
processDBConnDetails(wo);
}
}
}
// statuses for worksorders in this system
public enum job_status
{
Pending,
InProgress,
Completed
}
public struct DbConnDetails
{
public string username { get; set; } // username
public string password { get; set; } // password
public string database { get; set; } // database
public int conn_num { get; set; } // this objects connection number.
public ArrayList woList { get; set; } // list of works orders for this connection
// this constructor just sets the db connection details
// the woList array will get created later .. not a lot later but a bit.
public DbConnDetails(string username, string password, string database, int conn_num) : this()
{
this.username = username;
this.password = password;
this.database = database;
this.conn_num = conn_num;
woList = new ArrayList();
}
}
// Declare a delegate type for processing a DbConnDetails:
public delegate void ProcessDbConnDetailsDelegate(DbConnDetails dbConnDetails);
}
LoginBox.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WorksOrderFactory
{
public partial class LoginBox : Form
{
public LoginBox()
{
InitializeComponent();
}
private void LoginBox_Load(object sender, EventArgs e)
{
this.Visible = true;
this.Show();
//usernameText.Text = "Username";
//new Font(usernameText.Font, FontStyle.Italic);
}
private void cancelBtn_Click(object sender, EventArgs e)
{
this.Close();
}
private void loginBtn_Click(object sender, EventArgs e)
{
// set up a connection details object.
bool success = WorksOrderClient.createDBConnDetObj(usernameText.Text, passwordText.Text, databaseText.Text);
}
private void LoginBox_Load_1(object sender, EventArgs e)
{
}
}
}
Any ideas??
Cheers,
m
The one thing jumps out when comparing the definition of the delegate with the definition of the method you're trying to use:
static void CreateLabelInPanel(DbConnDetails dbcd)
public delegate void ProcessDbConnDetailsDelegate(DbConnDetails dbConnDetails)
CreateLabelInPanel should probably not be declared as static.
The compiler is just saying that the method you are providing to a delegate is not matching the signature expected by the delegate.
So, in your case.
//To get this line working...
wodb.ProcessDbConnDetails(new ProcessDbConnDetailsDelegate(SomeMethod1));
//The method signature should be like this.
static void SomeMethod1(DbConnDetails dbcd)
//OR even this -- Instance/Static methods can be supplied to same delegate.
void SomeInstanceMethod(DbConnDetails dbcd)..
And if not, the compiler would complain.
Also, by any chance, do you have two classes with the name "DbConnDetails" ???
My best guess is you are referring to "DbConnDetails" that lies in different namespace than the one expected by the delegate.
thanks #amby and #massif and anyone else I may have missed.
This was a school boy error.
It turns out I had another file (which I thought I'd deleted) that also contained a class and constructor called DbConnDetails. I did a search for DbConnDetails in the solution.
I renamed that class/constructor and the filename as well, to be safe.
I then declared
static void CreateLabelInPanel(DbConnDetails dbcd)
which means that the app now compiles/builds again.
Thanks again to everyone.

TextBox not updating in C#

Specifically looking at the arrive method in the Customer class. I am using a for loop to create instances of the customer class, and when I try to write out their arrival times to a textBox (Just for testing purposes) the text box does not update. Why is this?
This is just a small simulation project for my Computing class. It is in its early stages, and is probably wrong in a lot of places!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace QueueSimulation
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void Form1_Load(object sender, EventArgs e)
{
MessageBox.Show("The form has loaded");
}
public void goButton_Click(object sender, EventArgs e)
{
Initialisers init = new Initialisers();
Customer customer = new Customer();
customer.Arrive();
}
private void stopButton_Click(object sender, EventArgs e)
{
// put code here to break out of the program
}
}
public class Customer : Initialisers
{
int waitingTime;
int arrivalTime;
int arrivalInterval;
Initialisers init = new Initialisers();
public void Arrive()
{
Customer[] customer = new Customer[1000];
int counter = 0;
for (int i = 1; i <= 10; i++)
{
customer[i] = new Customer();
customer[i].TimeArrived();
displayArrival.Text = displayArrival.Text + customer[i].TimeArrived().ToString();
// Implement something to either show the time in the queue if needed
Thread.Sleep(init.CustomerArriveTime*100);
}
MessageBox.Show("All of the customers have arrived");
}
public string TimeArrived()
{
return Convert.ToString(DateTime.Now);
}
public void Leave()
{
}
public void GetServed()
{
}
}
public class Server
{
bool servingStatus;
int servingTime;
public void Serve()
{
}
}
public class Initialisers : Form1
{
private int cust_no = 3;
public int CustomerArriveTime
{
get
{
return cust_no;
}
set
{
cust_no = value;
}
}
private int s_time = 4;
public int serveTime
{
get
{
return s_time;
}
set
{
s_time = value;
}
}
}
}
Pass to the Arrive the instance of the textbox object created on your Form1.
public void Arrive(TextBox displayArrival)
Why are you inheriting the Form1 in Initialiserz? It's better to pass the reference to Form1 instead of inheritance in this case.
This seems overly complex. Try to model the real world. What is Initialisers, and why do you have an inheritance tree: Customer > Initialisers > Form1?
You're customer is writing to its own TextBox, instead of the TextBox you're looking at (the one from the Form that is visible).
Why not have a method Arrive that sets a private field to DateTime.Now. Then, ask the Customer its TimeArrived, which returns this field. In your Form, call these methods as much as needed in your loop.
This also seperaties command (Arrive) from query (TimeArrived) + keeps your inheritance more logical.
You might not even need Initialisers anymore. And don't let Customer inherit from Form, because a Customer isn't a Form.
I think there is more of a design issue here, you are creating instances of customer inside customer.
Your customer Arrive method should probably be a function inside the another class, like below, customer should just define what a customer is. Processing them should be handled by a different class.
class Customer
{
int waitingTime;
int arrivalTime;
int arrivalInterval;
// etc...
}
class ProcessCustomers
{
pubic void Arrive()
{
// etc...
}
}
public void goButton_Click(object sender, EventArgs e)
{
Initialisers init = new Initialisers();
ProcessCustomers CustomerQueue = new ProcessCustomers();
CustomerQueue .Arrive();
}
But for the text box issue you will have to expose a property in the form class and set it like that,
string ArrivalTime
{
get
{
return textBox1.Text;
}
set
{
textBox1.Text = value;
}
}

Categories