public int dialog()
{
Form prompt = new Form(); // creates form
//dimensions
prompt.Width = 300;
prompt.Height = 125;
prompt.Text = "Adding Rows"; // title
Label amountLabel = new Label() { Left = 50, Top = 0, Text = "Enter a number from 1-50" }; // label for prompt
amountLabel.Font = new Font("Microsoft Sans Serif", 9.75F);
TextBox value = new TextBox() { Left = 50, Top = 25, Width = prompt.Width / 2 }; // text box for prompt
Button confirmation = new Button() { Text = "Ok", Left = prompt.Width / 2 - 50, Width = 50, Top = 50 }; // ok button
confirmation.Click += (sender, e) => { prompt.Close(); }; // if clicked it will close
prompt.AcceptButton = confirmation; // enter
prompt.KeyPreview = true;
prompt.KeyDown += (sender, e) =>
{
if (e.KeyCode == Keys.Escape) prompt.DialogResult = DialogResult.Cancel; // user presses ESC key to close
};
// adding the controls
prompt.Controls.Add(value);
prompt.Controls.Add(confirmation);
prompt.Controls.Add(amountLabel);
prompt.ShowDialog();
// returning and checking if int block
int num;
Int32.TryParse(value.Text, out num);
return num;
}
This is the full code. The short version of the code is:
Label amountLabel = new Label() { Left = 50, Top = 0, Text = "Enter a number from 1-50" };
prompt.Controls.Add(amountLabel);
The problem is that it will only display up to "Enter a number". It won't display the full text for some reason. I tried shorter "E" and it worked. I even tried "Enter a number from" but it still didn't fully display.
You could enable AutoSize, which is set to true by default if you create it via the designer:
Label amountLabel
= new Label { AutoSize = true, Left = 50, Top = 0, Text = "Enter a number from 1-50" };
Set the width of the label:
Label amountLabel = new Label() { Left = 75, Top = 0, Width = 1000, Text = "Enter a number from 1-50" };
Don't make the width that wide, though. I just wanted to make sure the text fits without testing different values.
I was surprised that it didn't adjust the width automatically.
Set the Label's AutoSize property to true.
Label amountLabel = new Label() { AutoSize=true, Left = 50, Top = 0, Text = "Enter a number from 1-50" };
Related
I'm working on a personal project where I'm building a notes generator, and I have this TextBox dynamically created everytimes a button is clicked, it works fine just like how I expected but things gets weird when I tried to name each of these TextBox to different name by using a loop Name = "Note" + i where i is the loop variable.
So what I was expecting to happens is that each of the TextBox names to be something like Note1 Note2 Note3 ... but instead when I retrieved each of the TextBox name to a MessageBox in the same loop which is used to generates the TextBox, the MessageBox throws this: Note 1 Note 1 Note 1 ... instead when I clicked the button thrice.
int curr = 0;
private void guna2Button1_Click(object sender, EventArgs e) {
int top = 25;
int h_p = 170;
curr++;
for(int i=1; i<curr+1; i++) {
// Notes
var new_note = new Guna2TextBox() {
Text = "Title\n",
Name = "Note" + i,
Multiline = true,
AcceptsTab = true,
AcceptsReturn = true,
WordWrap = false,
ScrollBars = ScrollBars.Vertical,
Width = 220,
Height = 110,
BorderRadius = 8,
Font = new Font("Bahnschrift", 13),
ForeColor = Color.White,
FillColor = ColorTranslator.FromHtml("#1E1E1E"),
BorderColor = ColorTranslator.FromHtml("#2C2C2C"),
Location = new Point(450,top)
};
MessageBox.Show(i.ToString());
top += h_p;
flowLayoutPanel1.Controls.Add(new_note);
curr = 0;
}
}
The problem is caused by the fact that inside the loop you set always curr back to zero. And the loop is not needed at all because you want to add a textbox at each click. So you just need to look at the Count property of the FlowLayoutPanel and use that value to prepare the name.
Another problem to solve is how to position the next control inside the panel but again you could calculate easily with a the Count property
private void guna2Button1_Click(object sender, EventArgs e)
{
int nextTop = 25 + (flowLayoutPanel.Controls.Count * 170);
var new_note = new Guna2TextBox() {
Text = "Title\n",
Name = "Note" + flowLayoutPanel.Controls.Count + 1,
.....
Location = new Point(450,nextTop)
};
flowLayoutPanel1.Controls.Add(new_note);
}
I don't think you need to use the For loop in this case. You can just use the variable curr for each textboxes. So instead of the For loop, you can use this :
int top = 25;
int h_p = 170;
curr++;
var new_note = new Guna2TextBox() {
Text = "Title\n",
Name = "Note" + curr,
Multiline = true,
AcceptsTab = true,
AcceptsReturn = true,
WordWrap = false,
ScrollBars = ScrollBars.Vertical,
Width = 220,
Height = 110,
BorderRadius = 8,
Font = new Font("Bahnschrift", 13),
ForeColor = Color.White,
FillColor = ColorTranslator.FromHtml("#1E1E1E"),
BorderColor = ColorTranslator.FromHtml("#2C2C2C"),
Location = new Point(450,top)
top += h_p;
flowLayoutPanel1.Controls.Add(new_note);
};
I am working with Winforms and I have a question about making these more dynamic. For instance I can create a winform that has a group of text boxes that displays data however how would I make this dynamic? In terms of the number of text boxes the user can see depends on what data is found?
I know I can do something along the lines of the below:
TextBox tb = new TextBox();
In my scenario I have an application that reads through a bunch of documents and if a $ is found then a prompt appears asking the user to input a proper value, however, if the document has a lot of values that need updating then this is a lot of dialog boxes. So a good way to resolve this is to have the dialog box appear at the end (after the file has been read) with all the values that need updating and the user can update all these at once.
The problem that I see is that the number of values that need to be displayed can be anything from 1 on wards, which means the loop would need to account for this.
My current code is as below;
foreach (FileInfo fi in rgFiles)
{
current++;
fileProcessBar.Value = current / count * 60 + 40;
string[] alllines = File.ReadAllLines(fi.FullName);
for (int i = 0; i < alllines.Length; i++)
{
if (alllines[i].Contains("$"))
{
// prompt
int dollarIndex = alllines[i].IndexOf("--");
Regex regex = new Regex(#"(--.{1,100})");
var chars = regex.Match(alllines[i]).ToString();
string PromptText = chars.Replace("-", "");
string promptValue = CreateInput.ShowDialog(PromptText, fi.FullName);
if (promptValue.Equals(""))
{
}
else
{
alllines[i] = alllines[i].Replace("$", promptValue);
File.WriteAllLines(fi.FullName, alllines.ToArray());
}
}
}
prompt method:
public static string ShowDialog(string text, string caption)
{
Form prompt = new Form()
{
Width = 600,
Height = 150,
FormBorderStyle = FormBorderStyle.FixedDialog,
Text = caption,
StartPosition = FormStartPosition.CenterScreen
};
Label textLabel = new Label() { Left = 50, Top = 15, Width = 500, Text = text };
TextBox textBox = new TextBox() { Left = 50, Top = 52, Width = 500 };
Button confirmation = new Button() { Text = "Add", Left = 450, Width = 100, Top = 72, DialogResult = DialogResult.OK };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(textBox);
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.AcceptButton = confirmation;
prompt.MaximizeBox = false;
return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
}
My question is how can a winform be more dynamic as in terms of size and what is displayed? how can I create a new form without specifying size and position? but still not being a jumbled mess?
Make a new Form with a certain size. Then add a FlowLayoutPanel to the form which has almost the same width as the form and almost the same height. Leave enough space for the button that you need:
In the panel properties set the fields AutoSize to true and AutoSizeMode to GrowAndShrink:
Don't forget to specify the FlowDirection:
this.panel.FlowDirection = FlowDirection.TopDown;
Now you need just a method which adds your prompting controls to the controls of the FlowLayoutPanel (which will order them in an automatic fashion) :
public void AddToCanvas(string text)
{
this.flowLayoutPanel1.Controls.Add(new Label() {Text = text});
this.flowLayoutPanel1.Controls.Add(new TextBox());
Resize();
}
And a resize method to adjust the form to the amount of current controls inside it:
public void Resize()
{
Size s = new Size();
s.Height = this.flowLayoutPanel1.Height + this.button_Accept.Height +
(this.flowLayoutPanel1.Controls.Count * 10) + y_offset;
s.Width = this.flowLayoutPanel1.Width + 10;
this.MaximumSize = s;
this.Size = s;
}
With this input:
random text
$ Name
$ Address
random text
$ Age
random text
$ Planet
$ Continent
random text
$ StarSystem
I get the following Result:
EDIT:
Create a variable after you have read the contents of one file (before you loop through the lines):
DynamicPrompt dp = new DynamicPrompt("YourCaption");
for (int i = 0; i < alllines.Length; i++)
{
if (alllines[i].Contains("$"))
{
Start the loop and if you get to the important line call
dp.AddToCanvas(PromptText);
I'm currently designing a WinForms music player and I'm having some trouble figuring out how to set what a button does when the button is created via
Controls.Add(new Button(){})
The code I'm currently using is a while loop inside of which is the code to create a button name + x where x is a value that increments at the end of the loop. What i would like to do is set it so that on click the button will execute the function to play music which is named say "mpPlay". What would be the best way to go about this?
Here is the current code I'm using:
while (trackNoReader.Read())
{
flpTrackNo.Controls.Add(new Button()
{
Name = "btnTrackNo" + x,
Text = trackNoReader[0] as string,
BackColor = Color.Transparent,
FlatStyle = FlatStyle.Flat,
AutoSize = false,
Dock = DockStyle.Top,
Width = flpArtist.Width,
ForeColor = ColorTranslator.FromHtml("#444444"),
Font = new Font("Trebuchet MS", 9),
Enabled = true,
TextAlign = ContentAlignment.MiddleLeft,
FlatAppearance =
{
BorderSize = 0
},
});
x++;
}
If you wish to see the source code you can download the git repository here. Many Thanks - Ross
[EDIT]
Here's the code for mpPlay()
public void mpPlay(int x, string Column)
{
MySqlCommand selectPath = new MySqlCommand("SELECT" + Column + "FROM Music WHERE TrackNo=" + x);
selectPath.Connection = DB.connect;
MySqlDataReader readerPath = selectPath.ExecuteReader();
while (readerPath.Read())
{
path = readerPath[0] as string;
path = path.Replace("\"", "\\");
}
mpPlayer.Open(path);
mpPlayer.Play();
}
You could have a simple helper method like this:
public Button AttachMethodToButton(Button b, Action buttonMethod)
{
b.Click += (s, e) => buttonMethod();
return b;
}
which you would call like this:
flpTrackNo.Controls.Add(AttachMethodToButton(new Button()
{
// ... button properties like you already have
},
mpPlay)); // I'm assuming 'mpPlay' is a void method
If you want to call mpPlay with arguments, you'd call it like this:
flpTrackNo.Controls.Add(AttachMethodToButton(new Button()
{
// ... button properties like you already have
},
() => mpPlay(intParam, stringParam))); // replace intParam and stringParam with whatever arguments you want here
while (trackNoReader.Read())
{
flpTrackNo.Controls.Add(new Button()
{
Name = "btnTrackNo" + x,
Text = trackNoReader[0] as string,
BackColor = Color.Transparent,
FlatStyle = FlatStyle.Flat,
AutoSize = false,
Dock = DockStyle.Top,
Width = flpArtist.Width,
ForeColor = ColorTranslator.FromHtml("#444444"),
Font = new Font("Trebuchet MS", 9),
Enabled = true,
TextAlign = ContentAlignment.MiddleLeft,
FlatAppearance =
{
BorderSize = 0
},
});
// Adds Click event handler to last added button
flpTrackNo.Controls[flpTrackNo.Controls.Count - 1].Click += (sender, args) =>
{
// Call the function to play a sound
// Additionally the sender gives you the specific button as object
};
x++;
}
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 7 years ago.
Improve this question
I have a class called "AddChips" it's basically Prompt Dialog with some buttons and a TextBox the user enter's some data in it and i want to get the data that he just entered and send it back to some other class let's say "Form1" and give the data to integer called Chips
public static string ShowDialog(string text, string caption)
{
Form prompt = new Form();
prompt.Width = 500;
prompt.Height = 150;
prompt.FormBorderStyle = FormBorderStyle.FixedDialog;
prompt.Text = caption;
prompt.StartPosition = FormStartPosition.CenterScreen;
Label textLabel = new Label() { Left = 50, Top = 20, Text = text };
TextBox textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
Button confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70, DialogResult = DialogResult.OK };
Button leaveApp = new Button() { Text = "No", Left = 250, Width = 100, Top = 70, DialogResult = DialogResult.OK };
confirmation.Click += (sender, e) => { new Form1() { Chips = int.Parse(textBox.Text) }; };
leaveApp.Click += (sender, e) => { Application.Exit(); };
prompt.Controls.Add(textBox);
prompt.Controls.Add(confirmation);
prompt.Controls.Add(leaveApp);
prompt.Controls.Add(textLabel);
textLabel.Width = 300;
prompt.AcceptButton = confirmation;
return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
}
I have used on prompt form Like this:
public string ValueIWant { get; set; }
private void btnSetValueIWant_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtbxValue.Text))
{
ValueIWant= txtbxValue.Text;
this.DialogResult = System.Windows.Forms.DialogResult.OK;
Close();
}
}
and on the other form i get Value:
frmValue f= new frmValue ();
if (f.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string ValueIWantFromProptForm=f.ValueIWant ;
}
It Works for me.
So for this assignment in class I'm making a richtextbox editor in C# winforms, in this assignment I have to include a find function, but I can't seem to get the hang of it
EDIT: it closes every time I click the search button, but that's not what I want, I want it to close when the user closes the actual dialog via the X in the top right, the search button should just highlight the found string by using the .Find() method
Here's my code up until now:
private void zoekenToolStripMenuItem_Click(object sender, EventArgs e)
{
string searchValue = SearchDialog();
Search(searchValue);
}
public string SearchDialog()
{
Form findDialog = new Form();
findDialog.Width = 500;
findDialog.Height = 142;
findDialog.Text = "Zoeken";
Label textLabel = new Label() { Left = 10, Top = 20, Text = "Zoek naar:", Width = 100 };
TextBox inputBox = new TextBox() { Left = 150, Top = 20, Width = 300};
Button search = new Button() { Text = "Zoek", Left = 350, Width = 100, Top = 70 };
search.Click += (object sender, EventArgs e) => { findDialog.Close(); };
findDialog.Controls.Add(search);
findDialog.Controls.Add(textLabel);
findDialog.Controls.Add(inputBox);
findDialog.ShowDialog();
return (string)inputBox.Text;
}
void Search(string searchValue)
{
rtxtInhoud.Find(searchValue);
}
The part:
search.Click += (object sender, EventArgs e) => { findDialog.Close(); };
is what I'm really stuck on
Thanks in advance
EDIT: here's something that I tried to do, which didn't work
public string SearchDialog()
{
Form findDialog = new Form();
findDialog.Width = 500;
findDialog.Height = 142;
findDialog.Text = "Zoeken";
Label textLabel = new Label() { Left = 10, Top = 20, Text = "Zoek naar:", Width = 100 };
TextBox inputBox = new TextBox() { Left = 150, Top = 20, Width = 300};
Button search = new Button() { Text = "Zoek", Left = 350, Width = 100, Top = 70 };
Button findNext = new Button() { Text = "Volgende", Left 250, Width = 100, Top = 70};
search.Click += (object sender, EventArgs e) => { rtxtInhoud.Find(inputBox.Text); };
findDialog.Controls.Add(search);
findDialog.Controls.Add(textLabel);
findDialog.Controls.Add(inputBox);
findDialog.ShowDialog();
return (string)inputBox.Text;
}
This waits for the Dialog to be closed before highlighting the found string. Which is NOT what I want, I want it to keep the Dialog open, but still highlight the text
it closes every time I click the search button
Yes, that's because you added an event handler to the search button that closes the form:
search.Click += (object sender, EventArgs e) => { findDialog.Close(); };
but that's not what I want, I want it to [...]
Then write the code in that handler such that it does what you actually want it to do, instead of having it close the form.
In your main form code, create a method that searches your text and highlights a found string. Then hook this method up to your search dialog button like the sample below. Also, I think you should call form.Show() instead of .ShowDialog(), so the other form can respond to input.
private void HighlightString(string stringToHighlight)
{
// Code here to search your text and highlight a string.
}
private void SearchDialog()
{
var findDialog = new Form {Width = 500, Height = 142, Text = "Zoeken"};
var textLabel = new Label() {Left = 10, Top = 20, Text = "Zoek naar:", Width = 100};
var inputBox = new TextBox() {Left = 150, Top = 20, Width = 300};
var search = new Button() {Text = "Zoek", Left = 350, Width = 100, Top = 70};
search.Click += (object sender, EventArgs e) => HighlightString(inputBox.Text);
findDialog.Controls.Add(search);
findDialog.Controls.Add(textLabel);
findDialog.Controls.Add(inputBox);
findDialog.Show();
}
Use this code:
Application.Exit();