C# Form inheritance and transfer of data - c#

I have 2 different Forms. My first form Form1 is the main form that has a TextBox called textbox1. My other form is called FontSettings and is supposed to be used so Form1 can inherit FontSettings data. I am trying to send a string and 2 integers from FontSettings to Form1. It looks like this.
FontSettings:
Form1 form1 = new Form1();
form1.insertFont(family, size, color);
Form1:
public void insertFont(string a, int b, string c)
{
if (textBox1.SelectionLength > 0)
{
xx = textBox1.SelectedText;
textBox1.SelectedText = textBox1.SelectedText.Replace(xx, "" + a + "\" + b + c + "a");
}
else
{
textBox1.Paste("" + a + "\" + b + c + "a");
}
}
The string and both integers used, are public.
Someone please describe to me what I am doing wrong?

Simples. See the below code which opens FontSettings form from 'form1'
FontSettings newform = new FontSettings();
newform.ShowDialog();
MessageBox.Show(newform.MyString);
MessageBox.Show(string.Format("{0}", newform.MyInt1));
MessageBox.Show(string.Format("{0}", newform.MyInt2));
Then in the FontSettings form, create some public properties so they can be referenced from 'form1'
public string MyString { get; set; }
public int MyInt1 { get; set; }
public int MyInt2 { get; set; }
Then in a button click do the following:
private void button1_Click(object sender, EventArgs e)
{
MyString = "some value here...";
MyInt1 = 28;
MyInt2 = 77;
this.Close();
}

You want to modify form1 property from forsettings, one way to do it is find the form1 contrls and modify it directly as below
private void button1_Click(object sender, EventArgs e)
{
TextBox t = Application.OpenForms["Form1"].Controls["textBox1"] as TextBox;
t.Text = "some value here...";
// do the same for the other two controls
this.Close();
}

From your description,it sounds like you are making a text editor kind of application like Notepad.Well, if this is the case then its a lot easier to use three static fields.The code below will make this clear.
To proceed define three static fields in Form1 class,like this;
public static string family="";
public static int size=0;
public static string color="";
I guess you have three TextBoxes' and a Close Button on class FontSettings,if this is so,then add the code below to Click Event of Button;
if (!String.IsNullOrEmpty(textBoxFamily.Text))//Check if textBoxFamily is not empty.
{
Form1.family = textBoxFamily.Text;
if (!String.IsNullOrEmpty(textBoxSize.Text))//Check if textBoxSize is not empty.
{
Form1.size = Convert.ToInt32(textBoxSize.Text);
if (!String.IsNullOrEmpty(textBoxColor.Text))//Check if textBoxColor is not empty.
{
Form1.color = textBoxColor.Text;
this.Close();//If everything happens correctly,close FontSettings.
}
}
}
Now as we have declared the fields in Form1,we can use their values directly,like this;
public void insertFont()
{
if (textBox1.SelectionLength > 0)
{
xx = textBox1.SelectedText;
textBox1.SelectedText = textBox1.SelectedText.Replace(xx, "" + family + "\" + size + color + "a");
}
else
{
textBox1.Paste("" + family + "\" + size + color + "a");
}
}
Hope it's enough to get you back on track.If there's anything left,please inform me.

Related

How to add an item with the button that can delete this item c# winforms

Im trying to make an app that adds shopping items with the price(just for education purpose). I want to add a button as well so that I can delete this item if I want too. this is what Ive done:
class ShopItem
{
string name;
decimal price;
int labelNumber;
public ShopItem(string name, decimal price, int labelNumber)
{
this.name = name;
this.price = price;
this.labelNumber = labelNumber;
}
public string GetName()
{
return name;
}
public decimal GetPrice()
{
return price;
}
public int GetLabelNumber()
{
return labelNumber;
}
}
Then in my main class:
public partial class Form1 : Form
{
List<ShopItem> shopItems = new List<ShopItem>();
List<Button> buttons = new List<Button>();
List<Label> labelsList = new List<Label>();
int shopItemNumber;
int top = 50;
int left = 50;
public Form1()
{
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
this.shopItemNumber = shopItems.Count;
label3.Text = "";
label3.Text = shopItemNumber.ToString();
shopItems.Add(new ShopItem(textBox1.Text, Convert.ToDecimal(textBox2.Text), shopItemNumber));
AddLabel();
AddAButton();
}
void AddAButton()
{
Button newButton = new Button();
buttons.Add(newButton);
newButton.Left = left + 100;
newButton.Top = top;
newButton.Text = "DELETE";
panel1.Controls.Add(newButton);
top += 40;
}
void AddLabel()
{
Label newLabel = new Label();
labelsList.Add(newLabel);
newLabel.Left = left;
newLabel.Top = top;
newLabel.Text = shopItems[shopItemNumber].GetName() + " " + shopItems[shopItemNumber].GetPrice();
panel1.Controls.Add(newLabel);
}
}
Im adding new objects and then checking the list count so that I know each item number. Now I dont know how to make buttons to remove each item. I would also like to know what is the best practice for this type of tasks? I dont want to use database as its too complicated for now, just make it in runtime? How would you, advanced guys, would make it?
I managed to do something like this based on your answers:
public partial class Form1 : Form
{
List<ShopItem> shopItems = new List<ShopItem>();
List<Button> buttons = new List<Button>();
List<Label> labelsList = new List<Label>();
int shopItemID;
int top = 50;
int left = 50;
public Form1()
{
InitializeComponent();
shopItemID = 0;
}
private void Button1_Click(object sender, EventArgs e)
{
int shopItemID = this.shopItemID;
label3.Text = "";
label3.Text = shopItemID.ToString();
decimal price;
if(Decimal.TryParse(textBox2.Text.Replace(",", "."), out price))
{
shopItems.Add(new ShopItem(textBox1.Text, price, shopItemID));
label3.Text = price.ToString();
AddLabel();
AddAButton();
this.shopItemID++;
}
else
{
label3.Text = "Wrong price format provided";
}
}
void AddAButton()
{
Button newButton = new Button();
buttons.Add(newButton);
newButton.Left = left + 100;
newButton.Top = top;
newButton.Text = "DELETE";
panel1.Controls.Add(newButton);
top += 40;
newButton.Tag = this.shopItemID;
newButton.Click += DeleteClicked;
}
void DeleteClicked(object sender, EventArgs e)
{
Button button = (Button)sender;
int itemNumber = (int)button.Tag;
ShopItem item = shopItems[itemNumber];
button.Dispose();
labelsList[itemNumber].Dispose();
}
void AddLabel()
{
Label newLabel = new Label();
labelsList.Add(newLabel);
newLabel.Left = left;
newLabel.Top = top;
newLabel.Text = shopItems[shopItemID].GetName() + " " + shopItems[shopItemID].GetPrice();
newLabel.Tag = this.shopItemID;
panel1.Controls.Add(newLabel);
}
}
It's working as I wanted it. The question is: The way I did it was according to the right coding practice?
The other question is: I would like to add placement functionality so that if some item is deleted other items go up the way. Should I use some position list? Can All of those items be contained within a ShopItem class? I mean, can I add button, label and other stuff withing this class so they all are created at the same time and becomes one object?
First thing you'll want to do is start using IDs instead of the count. The reason is, let's say you have 5 items (0 through 4) and you delete one. Now when you add another new one, it will get #4 because the count is 4 again (before adding the new one to the list), which means you'll have two #4s.
What you'll want to do instead is something like look for the highest existing number and add 1 to it:
this.shopItemNumber = shopItems.Any() ? shopItems.Max(item => item.labelNumber) + 1 : 0;
Now for the Delete button, just pass the item's number to the AddAButton() method:
AddAButton(shopItemNumber);
...and change the method's signature accordingly:
void AddAButton(int itemNumber)
And then in the AddAButton() method, add that number to the Tag property (you'll see why below):
newButton.Tag = itemNumber;
You'll also need to subscribe to the button's Click event:
newButton.Click += DeleteClicked;
Then create the DeleteClicked() method. This is where you'll make use of that Tag property:
void DeleteClicked(object sender, EventArgs e)
{
Button button = (Button)sender;
int itemNumber = (int)button.Tag;
ShopItem item = shopItems.FirstOrDefault(item => item.labelNumber = itemNumber);
if (item != null)
shopItems.Remove(item);
}
You'll also want to clean up the controls. Make sure to Dispose() them after removing them.
You just have to identify what Label belongs to the button.
Make AddLabel return the label it just created:
Label AddLabel()
{
Label newLabel = new Label();
labelsList.Add(newLabel);
newLabel.Left = left;
newLabel.Top = top;
newLabel.Text = shopItems[shopItemNumber].GetName() + " " + shopItems[shopItemNumber].GetPrice();
panel1.Controls.Add(newLabel);
return newLabel;
}
Pass the label to the new button, and add code to remove it. Store the current shopItem in a variable, so you can access it from the removal code.
void AddAButton(Label newLabel)
{
Button newButton = new Button();
buttons.Add(newButton);
newButton.Left = left + 100;
newButton.Top = top;
newButton.Text = "DELETE";
panel1.Controls.Add(newButton);
top += 40;
// Store the current shopItem in the context (for the lambda)
var shopItem = shopItems[shopItemNumber]
newButton.Click += (s, e) => {
panel1.Controls.Remove(newLabel);
panel1.Controls.Remove(newButton);
newLabel.Dispose();
newButton.Dispose();
shopItems.Remove(shopItem);
}
}
Since controls are IDisposable, it is advised to call Dispose after removing them.

How to get rid of flicker [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
namespace stock4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.chart1.AxisViewChanged += chart1_AxisViewChanged;
this.chart1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart1_MouseMove);
}
private void CandleStick_Load(object sender, EventArgs e)
{
CHART();
}
string path = #"C:\Users\1\Documents\Visual Studio 2013\Projects\stock3\stock3\bin\Debug\#S-PG1440.csv";
static int count = System.IO.File.ReadAllLines(#"C:\Users\1\Documents\Visual Studio 2013\Projects\stock3\stock3\bin\Debug\#S-PG1440.csv").Length;
int[] index = new int[count];
DateTime[] nums = new DateTime[count];
double[,] mass = new double[count, 4];
public void CHART()
{
//Here the data from the file is read and entered into the array.
//chart1.Series["price"].Points.AddXY(index[i], mass[i, 1], mass[i, 2], mass[i, 0], mass[i, 3]);
}
private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
{
//Autoscaling the graph
}
public static string str;
private void button1_Click(object sender, EventArgs e)
{
Form newForm = new Form();
newForm.DoubleBuffered = true;//Error 1 Cannot access
//protected member 'System.Windows.Forms.Control.DoubleBuffered'
//via a qualifier of type 'System.Windows.Forms.Form';
//the qualifier must be of type 'stock4.Form1'
//(or derived from it)
newForm.Show();
newForm.Width = 150;
newForm.Height = 230;
newForm.BackColor = Color.White;
newForm.Paint += new PaintEventHandler(MyPaintHandler);
}
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
chart1.ChartAreas[0].CursorX.SetCursorPixelPosition(e.Location, false);
chart1.ChartAreas[0].CursorY.SetCursorPixelPosition(e.Location, false);
int val = (int)chart1.ChartAreas[0].CursorX.Position;
if (val >= 0)
{
double current = chart1.ChartAreas[0].CursorY.Position;
str = "time: " + nums[val] + "\n" +
"current: " + current + "\n" +
"open: " + mass[val, 0] + "\n" +
"high: " + mass[val, 1] + "\n" +
"low: " + mass[val, 2] + "\n" +
"close: " + mass[val, 3];
}
}
static void MyPaintHandler(object objSender, PaintEventArgs pea)
{
Form newForm = (Form)objSender;
Graphics grfx = pea.Graphics;
grfx.DrawString(str, newForm.Font, Brushes.Black, 0, 0);
newForm.Invalidate();
Thread.Sleep(1);
}
}
}
I read the data from the form and pass it to another for display.
I create a form to display when a button event occurs(button1_Click).
Data for "str" is taken from another form.
Perhaps the second form is not needed?
I need a separate window from the main form to display the data.
UPDATED THE CODE! Part of the code is not on the subject was removed from the comments.
How do I place the string " newForm.DoubleBuffered = true " in "button1_Click" without errors? It is possible a code sample?
Forget about painting, doublebuffering etc.
Simply add a Label control to the 2nd form and access it in the chart's MouseMove event!
Make newForm a class level variable:
Form newForm = null;
In your button click write something like this:
newForm = new Form();
..
Label lbl = new Label() { Name = "myLabel", Parent = newForm };
newForm.Show();
In your MouseMove write something like this:
if (newForm != null && newForm.Controls.ContainsKey("myLabel"))
((Label)newForm.Controls["myLabel"]).Text = str;
Very simple, no flicker and you are free to style the Label in any way you like.

Dynamic text boxes and using them

I've generated some textboxes and i want to the user input data in them after it added to form and then i use the data in them for some calculations.
how can i use the data?
TextBox t3 = new TextBox();
t3.Top = 222 + ((addalternativebutton - 3) * 60);
t3.Left = 214;
t3.Width = 76;
t3.Height = 22;
t3.Name = "txtwaste" + addalternativebutton.ToString();
this.tabore.Controls.Add(t3);
ww[addalternativebutton] = Convert.ToDouble(t3.Text);
As I mentioned in the comments you need to preserve the textbox instances which you are creating dynamically. You can either use generic dictionary, if you need to deal with the names assigned to them or you can use generic list.
Following solution I provide you which uses generic list.
First thing needed is a list which will preserve the textboxes.
public partial class Form1 : Form
{
private List<TextBox> textBoxes;
private int textBoxCount; //This is used to provide unique names to the
//textboxes and to track the number of dynamic textboxes.
public Form2()
{
InitializeComponent();
}
}
Now in click event of the button the textbox is created, positioned and added to the list as well as Form.Controls.
private void button1_Click(object sender, EventArgs e)
{
textBoxCount += 1;
TextBox t3 = new TextBox();
t3.Top = 20 + (22 * textBoxCount); //You can put your own logic to set the Top of textbox.
t3.Left = 120;
t3.Width = 50;
t3.Height = 20;
t3.Name = "txtwaste" + textBoxCount; //You can use your own logic of creating new name.
this.Controls.Add(t3);
this.textBoxes.Add(t3);
}
Now when you want to calculate the sum of the values of all the textboxes on click of another button.
private void button2_Click(object sender, EventArgs e)
{
double totalValue = 0;
foreach (var textBox in textBoxes)
{
double currentValue;
if (double.TryParse(textBox.Text, out currentValue))
{
totalValue += currentValue;
}
}
// Displaying totalValue in a label.
lblTotalValue.Text = "Total Value : " + totalValue;
}
This should help you resolve your issue.

For Tchart in C#, how to make markstip show out both series name and label value when mouse over

I have a teechart which has multiple series and I want use the markstip to show out both label value and the series name when mouse over. How could I do that?
Chart.Tooltip1 = new Steema.TeeChart.Tools.MarksTip(Chart);
Chart.Tooltip1.Style = MarksStyles.Labelvalue;
Chart.Tooltip1.GetText += new Steema.TeeChart.(tooltip1_GetText);
You can use series' GetSeriesMark event for that, for example:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitializeChart();
}
private void InitializeChart()
{
tChart1.Series.Add(new Steema.TeeChart.Styles.Bar()).FillSampleValues();
tChart1[0].GetSeriesMark += Form1_GetSeriesMark;
tChart1[0].Marks.Visible = false;
tChart1.Tools.Add(new Steema.TeeChart.Tools.MarksTip());
}
void Form1_GetSeriesMark(Steema.TeeChart.Styles.Series series, Steema.TeeChart.Styles.GetSeriesMarkEventArgs e)
{
e.MarkText = "X: " + series.XValues[e.ValueIndex].ToString() + ", Y: " + series.YValues[e.ValueIndex].ToString() + " - " + series.ToString();
}
}

Accessing control from a different function in Winforms

I have a hopefully simple question, for which I could not google up any solution:
I would like to add labels buttons textboxes at runtime, which i can in the constructor of my Form, but I cannot access them outside of the constructor.
Something like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Label changeMe = new Label();
changeMe.AutoSize = true;
changeMe.Left = 50; changeMe.Top = 50;
changeMe.Text = "Change this text from other function";
changeMe.IsAccessible = true;
//changeMe.Name = "changeMe";
this.Controls.Add(changeMe);
}
private void btn_changeLabelText_Click(object sender, EventArgs e)
{
//Would like to achieve this:
//changeMe.Text = "You changed me !! ";
//But I found only this solution:
//Label l; l = (Label)this.Controls.Find("changeMe", true)[0]; l.Text = "You changed Me";
}
}
The solution I commented out is the only one I found, but I can't believe there isn't any better one then that. Is there a way to make my controls public for example? Whats a good way of solving this problem?
(The number of controls vary on every time I call my Dialogbox I am trying to design)
Thanks
EDIT --------------------------
After accepting Adil's answer, I stayed with the following solution, which I only find better as the originally outcommented this.Control.Find way, because I also want to have "n" Textboxes, and in thie way I can easily loop through them and read inputs.
public partial class Form1 : Form
{
public struct labels { public Label lbl; public int id; }
List<labels> lbls = new List<labels>();
public Form1()
{
InitializeComponent();
Label changeMe = new Label();
changeMe.AutoSize = true;
changeMe.Left = 50; changeMe.Top = 50;
changeMe.Text = "Change this text from other function";
changeMe.IsAccessible = true;
this.Controls.Add(changeMe);
labels newlabel = new labels();
newlabel.id = 137; newlabel.lbl = changeMe;
lbls.Add(newlabel);
}
private void btn_changeLabelText_Click(object sender, EventArgs e)
{
lbls.Find(i => i.id == 137).lbl.Text = "You changed me";
}
}
You declared the label inside constructor that makes it accessible only in constructor, ceclare label out side constructor at class scope as class member.
Label changeMe = new Label();
public Form1()
{
InitializeComponent();
Label changeMe = new Label();
changeMe.AutoSize = true;
changeMe.Left = 50; changeMe.Top = 50;
changeMe.Text = "Change this text from other function";
changeMe.IsAccessible = true;
//changeMe.Name = "changeMe";
this.Controls.Add(changeMe);
}

Categories