Interaction between two Forms and Threads - c#

What do I need:
I need a separate Form that shows some information from my Main Program/Class but the program must continue. So I decided to start the second window in a second thread. And after it is created I want to send data wich should be shown.
Where is the Problem: I have created a thread and generated the form but I can't fill date in this new Form.
My Code so far:
public partial class Form1 : Form
{
int number = 0;
Thread t1;
Form2 fm2 = new Form2();
//open the second Form
private void add_window_Click(object sender, EventArgs e)
{
t1 = new Thread(test);
if (!t1.IsAlive )
{
t1.Start();
}
else { MessageBox.Show("Thread allready runing"); }
}
public void test()
{
fm2.Gen();
}
// start the generitng of new data
private void sec_serein_Click(object sender, EventArgs e)
{
fm2.add_ser();
}
}
class Form2
{
Form FormX = new Form();
int number = 0;
Charting.ChartArea chartArea1 = new Charting.ChartArea();
Charting.Legend legend1 = new Charting.Legend();
Charting.Series series1 = new Charting.Series();
Charting.Chart chart1 = new Charting.Chart();
public void Gen()
{
// create an Form with a Charting Area
FormX.ShowDialog();
}
public void add_ser()
{
// For each Row add a new series
string seriesName = "Series_" + number;
number++;
chart1.Series.Add(seriesName);
chart1.Series[seriesName].ChartType = SeriesChartType.Line;
chart1.Series[seriesName].BorderWidth = 2;
Random rnd = new Random();
for (int i = 0; i < 20; i++)
{
string columnName = i.ToString();
int YVal = rnd.Next(0, 100);
chart1.Series[seriesName].Points.AddXY(columnName, YVal);
}
}
}

Related

How to create MaterialSingleLineTextField Controls dynamically

I would like to add MaterialSingleLineTextField dynamically to a Form.
I have used MaterialSkin NuGet package:
I am trying to create multiple MaterialSkin TextBoxes dynamically on Form.Load. But no Controls are displaying in the hosing Panel.
private void Form1_Load(object sender, EventArgs e)
{
int n = 5;
int pointX = 30;
int pointY = 40;
//panel1.Controls.Clear();
for (int i = 0; i < n - 1; i++)
{
MaterialSingleLineTextField a = new MaterialSingleLineTextField();
a.Text = (i + 1).ToString();
a.Visible = true;
a.Location = new Point(pointX, pointY);
panel1.Controls.Add(a);
panel1.Show();
pointY += 20;
}
}
This code block works perfectly fine for normal TextBoxes.
Is there any way to add MaterialSingleLineTextField dynamically?
A sample Form initialization with default Theme values.
The MaterialSkinManager is initialized in the Form Constructor, setting the Theme to MaterialSkinManager.Themes.LIGHT and default color scheme. The Form base Type is set to MaterialForm.
A specified number of MaterialSingleLineTextField controls is added to a parent container (a Panel), starting from a defined Location downwards.
These Controls are anchored to the parent and the Height is set to Parent.Font.Height + 4.
It's important that you specify the Size of these Controls, otherwise you'll get a minimal size that prevents the Controls from showing their content.
As you can see in the AddTextFields() method, it's important that you dispose of the previous Controls added to the Parent container, if you want to replace the existing with new ones. Even more important using this Library.
Calling the Clear() method of a Control.Controls collection (as in the line you have commented out) doesn't dispose of anything, those controls are still alive.
public partial class Form1 : MaterialForm
{
private readonly MaterialSkinManager msManager = null;
public Form1()
{
InitializeComponent();
msManager = MaterialSkinManager.Instance;
msManager.AddFormToManage(this);
msManager.Theme = MaterialSkinManager.Themes.LIGHT;
}
private void Form1_Load(object sender, EventArgs e)
{
AddTextFields(panel1, 5, new Point(30, 10), false);
}
private void AddTextFields(Control parent, int controlsCount, Point startPosition, bool ClearExisting)
{
if (clearExisting && parent.Controls.Count > 0) {
for (int i = parent.Controls.Count - 1; i >= 0; i--) {
parent.Controls[i].Dispose();
}
}
int controlHeight = parent.Font.Height + 4;
int yIncrement = 0;
for (int i = 0; i < controlsCount; i++) {
var textField = new MaterialSingleLineTextField() {
Text = (i + 1).ToString(),
Size = new Size(parent.ClientSize.Width - startPosition.X - 4, controlHeight),
Location = new Point(startPosition.X, startPosition.Y + yIncrement),
Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right
};
parent.Controls.Add(textField);
yIncrement += (controlHeight + 10);
}
}
private void matBtnChangeTheme_Click(object sender, EventArgs e)
{
msManager.Theme = MaterialSkinManager.Themes.DARK;
msManager.ColorScheme = new ColorScheme(Primary.Blue600, Primary.Blue900, Primary.Blue500, Accent.LightBlue200, TextShade.WHITE);
}
private void matBtnAddControls_Click(object sender, EventArgs e)
{
AddTextFields(panel1, 7, new Point(30, 10), true);
}
}
Sample functionality:

How to display Form Components from List

this question might be really stupid but here it is anyway. What I want my programm to do: When I press a button I want to add a DatePicker Component to a List and then display all the Components in the Main Form. However when I press the button it only adds the components but doesnt show them in the Form Window. No Errors are thrown. What do I have to do to display the DatePicker Components in the Main Form?
//class containing the List of Components
class Eintrag
{
static public List<DateTimePicker> Anfangszeit = new List<DateTimePicker>();
}
//Main Form Class
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Eintrag.Anfangszeit.Add(new DateTimePicker());
for (int i = 0; i < Eintrag.Anfangszeit.Count; i++)
{
Eintrag.Anfangszeit[i].Location = new System.Drawing.Point(30, 50 + 50*i);
Eintrag.Anfangszeit[i].Size = new System.Drawing.Size(200, 20);
Eintrag.Anfangszeit[i].Visible = true;
Eintrag.Anfangszeit[i].Show();
}
}
}
John Wu is right, you have to add the Controls to the Form via Controls.Add()
private void button1_Click(object sender, EventArgs e)
{
Eintrag.Anfangszeit.Add(new DateTimePicker());
for (int i = 0; i < Eintrag.Anfangszeit.Count; i++) {
Eintrag.Anfangszeit[i].Location = new System.Drawing.Point(30, 50 + 50 * i);
Eintrag.Anfangszeit[i].Size = new System.Drawing.Size(200, 20);
Eintrag.Anfangszeit[i].Visible = true;
this.Controls.Add(Eintrag.Anfangszeit[i]);
Eintrag.Anfangszeit[i].Show();
}
}

How do I display values under the cursor in the second form?

I draw a candlestick chart from the file data.
Create a new form(second form) when you click the button in which you want to display:
time, high, low, open, close.
namespace stock5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.Load += new System.EventHandler(this.CandleStick_Load);
}
private void CandleStick_Load(object sender, EventArgs e)
{
CHART();
}
public void CHART()
{
*************************************************
//The code reads the data from the file is skipped.
chart1.Series.Clear();
Series price = new Series("price");
chart1.Series.Add(price);
chart1.ChartAreas[0].CursorX.IsUserEnabled = true;
chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = true;
chart1.ChartAreas[0].AxisY.IsStartedFromZero = false;
chart1.Series["price"].ChartType = SeriesChartType.Candlestick;
chart1.Series["price"]["OpenCloseStyle"] = "Triangle";
chart1.Series["price"]["ShowOpenClose"] = "Both";
chart1.Series["price"]["PointWidth"] = "2.0";
chart1.Series["price"]["PriceUpColor"] = "Blue";
chart1.Series["price"]["PriceDownColor"] = "Red";
chart1.Series["price"].BorderColor = Color.Black;
chart1.Series["price"]["MaxPixelPointWidth"] = "2.0";
for (i = 0; i < count - 1; i++)
{
chart1.Series["price"].Points.AddXY(index[i], mass[i, 1], mass[i, 2], mass[i, 0], mass[i, 3]);//index, high, low, open, close
}
int INDEX = 0;
foreach (DataPoint point in chart1.Series["price"].Points)
{
point.AxisLabel = nums[INDEX].ToString();//Replacing the index values for the time(To avoid empty values when markets are closed on weekends)
INDEX++;
}
}
}
}
The second form in which you want to print values depending on the location of the cursor.
private void button1_Click(object sender, EventArgs e)
{
Form newForm = new Form();
newForm.Show();
newForm.Width = 170;
newForm.Height = 230;
}
And a passing question: how to get instead of indexes in the form of time?
There is multiple ways you can communicate with first form in time and here is one of it:
I assume your Form is your new form? (I will use it in my example as it is)
For this example i will create custom class (object) which i will be returning to newly created form every 0.2 sec.
So new object would be
public class MyNewObject
{
int Id { get; set; }
string Name { get; set; }
int Speed { get; set; }
}
So class of Form will look like this (at least code which is needed to perform this)
public partial class Form : Form
{
Timer t = new Timer();
private YourFirstForm myFirstForm;
public Form(YourFirstForm form)
{
InitializeComponents();
myFirstForm = form;
t.Interval = 200; //0.2 sec
Thread t1 = new Thread(FirstFormListener);
t1.Start();
}
private void FirstFormListner()
{
Timer t = new Timer();
t.Interval = 200; //0.2 sec
t.Tick += new EventHandler(timer1_Tick);
t.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
MyNewObject someData = myFirstForm.GetSomeData();
MessageBox.Show(someData.Name);
}
}
And inside your first form:
public partial class YourFirstForm : Form
{
string someString = "Some random string";
public YourFirstForm()
{
InitializeComponents();
}
public MyNewObject GetSomeData()
{
MyNewObject mno = new MyNewObject();
mno.Name = "Random name";
mno.Id = 1;
mno.Speed = 200;
return mno;
}
}
This is one way of doing it and i think it is practical since you can adjust interval of thick so set update time (on slower pc set it to lower value for faster you can to faster value). Also updating is done on separate thread so it doesn't affect your UI (freeze) and you can continue with job.

C# send values of dynamically created textboxes to another users of this program

I am working on project in which I need to send values of dynamiclly created textboxes.
I need values to be changed in another computer when I change It in mine.
This is my code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
static int itimes = 0;
static int i = 0;
public void textboxadd()
{
TextBox txt = new TextBox();
txt.Name = "Name" + i;
if (i == 0)
{
Point p = new Point(6, 43);
txt.Location = p;
}
else
{
Point p = new Point(6, 43 + 32 * i);
txt.Location = p;
}
txt.Size = new System.Drawing.Size(236, 26);
Properties.Settings.Default.name1 = txt.Text;
Properties.Settings.Default.Save();
groupBox1.Controls.Add(txt);
i++;
}
private void button1_Click(object sender, EventArgs e)
{
textboxadd();
int gps = groupBox1.Size.Height;
if (itimes == 0)
{
itimes++;
}
else
{
groupBox1.Size = new System.Drawing.Size(248, gps + 32);
}
}
}
If you don't understand my question please ask and I will answer.

Reference the Form in a separate class

I have a Windows Forms project in Visual Studio 2012 (C#)
I have a class called Gameboard in my project, and I need to reference this in a method in that class. How can I reference the Form in another class??
EDIT:
#Sergey
public class Gameboard
{
public Button[] buttonArray { get; set; }
public Gameboard(int numberofButtons) //Constructor method that is referencing the App.config for the dimensions value to make the board
{
if (numberofButtons <= 0)
throw new ArgumentOutOfRangeException("Invalid Grid"); //throws an exception for an invalid grid size if dimensions is equal to or less than zero
buttonArray = new Button[numberofButtons]; //creating an array the size of numberofButtons which is the dimensions value from App.config
Font font = new Font("Times New Roman", 36.0f); //creates an instance of the Font class
int sqrtY = (int) Math.Sqrt(numberofButtons);
int z = 0; //Counter for array
//Create the buttons for the form
//Adds the buttons to the form first with null values then changes the .Text to ""
for (int x = 0; x < sqrtY; x++)
{
for (int y = 0; y < sqrtY; y++)
{
buttonArray[z] = new Button();
buttonArray[z].Font = font;
buttonArray[z].Size = new System.Drawing.Size(100, 100);
buttonArray[z].Location = new System.Drawing.Point(100*y, 100*x);
buttonArray[z].Click += new EventHandler(button_click);
z++;
}
}//At the end of this loop, buttonArray contains a number of buttons equal to Dimensions all of which have a .Text property of ""
}
So there is plenty of other stuff after this in the Gameboard class, but so for the constructor I need to also pass in a Form instance? I'm just confused about the process.
Here is how I am called the constructor on the Form_Load
private void Form1_Load(object sender, EventArgs e)
{
try
{
//Read the App.Config file to get the dimensions of the grid
int dimensions = Convert.ToInt16(ConfigurationManager.AppSettings["dimensions"]);
//Create the gameboard object with all the buttons needed
Gameboard gb = new Gameboard(dimensions); //Calls the Gameboad constructor method
//Add buttons to the form
for (int x = 0; x < gb.buttonArray.Length; x++)
{
this.Controls.Add(gb.buttonArray[x]);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Pass the Form instance as a parameter to Gameboard constructor or method call.
i.e. in Form code:
Gameboard gameboard = new Gameboard(this);
or
Gameboard gameboard = new Gameboard();
gameboard.MyMethod(this);
and in Gameboard:
public void MyMethod(Form mainForm)
{
... //Whatever
}
UPDATE
For your code it will be:
public class Gameboard
{
...
public Gameboard(int numberofButtons, Form1 mainForm) //Constructor method that is referencing the App.config for the dimensions value to make the board
{
... // init all buttons
// for example
for (int i = 0; i<buttonArray.Length; i++)
{
mainForm.Controls.Add(buttonArray[i]);
}
}
}
and in Form1_Load:
private void Form1_Load(object sender, EventArgs e)
{
try
{
//Read the App.Config file to get the dimensions of the grid
int dimensions = Convert.ToInt16(ConfigurationManager.AppSettings["dimensions"]);
//Create the gameboard object with all the buttons needed
Gameboard gb = new Gameboard(dimensions, this); //Calls the Gameboad constructor method
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
By passing the instance of your form as a reference to your GameBoard class. E.g. in your startup method of your application.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var mainForm = new Form1();
var gameboard = new GameBoard(mainForm);
Application.Run(mainForm);
}

Categories

Resources