i`m trying to find a efficient way to define conditions for radio-buttons.
After selecting a Radio-Button i should disable or fill the text-boxes. Following an example:
private void Transportauftrag_CheckedChanged(object sender, EventArgs e)
{
groupBox1.Visible = true;
groupBox8.Visible = false;
StartGerät.Text = "";
StartBlockFach.Text = "";
StartTiefe.Text = "";
ZielGerät.Text = "";
ZielBlockFach.Text = "";
ZielTiefe.Text = "";
FehlerFehler.Text = "****";
FehlerBereich.Text = "****";
FehlerInfo.Text = "****";
Transportbefehl.Text = "";
Breite.Text = "";
Tiefe.Text = "";
Höhe.Text = "";
Typ.Text = "";
Folgeauftrag.Text = "";
Behälternummer.Text = "";
Reserve.Text = "";
StartGerät.Enabled = true;
StartBlockFach.Enabled = true;
StartTiefe.Enabled = true;
ZielGerät.Enabled = true;
ZielBlockFach.Enabled = true;
ZielTiefe.Enabled = true;
FehlerFehler.Enabled = false;
FehlerBereich.Enabled = false;
FehlerInfo.Enabled = false;
Transportbefehl.Enabled = true;
Breite.Enabled = true;
Tiefe.Enabled = true;
Höhe.Enabled = true;
Typ.Enabled = true;
Folgeauftrag.Enabled = true;
Behälternummer.Enabled = true;
Reserve.Enabled = true;
}
So now i should do this 7 times.
And for this i need over 400 Line of Codes in my WindowsFormsApp-File.
Are they any better way / solution to do this?
ok here are some suggestions. Basically if faced with such a problem then it indicates that you need an organizational structure. Otherwise one gets lost. As it appears from the picture of your GUI you already have GroupBoxes that organize this. All the labels and Textboxes inside that groupbox are in groupBox1.Controls. You can get them out in 1 blow even by type:
List<TextBox> allTextBoxesFromGroupBox1 = groupBox1.Controls.OfType<TextBox>().ToList();
Now you can iterate over it and write the same value for each Textbox:
foreach (TextBox tb in allTextBoxesFromGroupBox1)
{
tb.Text = "";
}
But you better make a method from it:
private void FillAllTextBoxes(GroupBox groupBox, string text)
{
List<TextBox> allTextBoxesFromGroupBox1 = groupBox.Controls.OfType<TextBox>().ToList();
foreach (TextBox tb in allTextBoxesFromGroupBox1)
{
tb.Text = "";
}
}
Now you can simply call it and pass the necessary input:
FillAllTextBoxes(groupBoxStart, "");
FillAllTextBoxes(groupBoxZiel, "");
FillAllTextBoxes(groupBoxFehler, "****");
FillAllTextBoxes(groupBoxParameter, "");
At this point we got rid of 17 Lines and introduced only 4
Proceeding... The next step would be the enabling of the controls. It seems that you treat again all Textboxes inside the same groupbox also the same. So we can introduce another parameter for the enabling part into the method:
private void FillAllTextBoxes(GroupBox groupBox, string text, bool enable)
{
List<TextBox> allTextBoxesFromGroupBox1 = groupBox.Controls.OfType<TextBox>().ToList();
foreach (TextBox tb in allTextBoxesFromGroupBox1)
{
tb.Text = "";
tb.Enabled = enable;
}
}
and this allows us to remove the rest of the lines entirely without introducing new lines of code:
FillAllTextBoxes(groupBoxStart, "", true);
FillAllTextBoxes(groupBoxZiel, "", true);
FillAllTextBoxes(groupBoxFehler, "****", false);
FillAllTextBoxes(groupBoxParameter, "", true);
So now you are down at 4 lines (I see only 4 groupboxes in your screenshot) of code
Related
I'm using this right now to clear a tic tac toe table on Microsoft Windows Forms
button1.Enabled = true;
button2.Enabled = true;
button3.Enabled = true;
button4.Enabled = true;
button5.Enabled = true;
button6.Enabled = true;
button7.Enabled = true;
button8.Enabled = true;
button9.Enabled = true;
button1.Text = "";
button2.Text = "";
button3.Text = "";
button4.Text = "";
button5.Text = "";
button6.Text = "";
button7.Text = "";
button8.Text = "";
button9.Text = "";
but it's too long so I wanted to use a for loop like this
for (int i = 1; i < 10; i++)
{
button[i].Enable = true;
button[i].Text = "";
}
but it doesn't work so could anyone suggest a solution?
you can iterate over Controls array of parent of buttons, for example you can move all buttons to a Panel and use foreach to iterate over all controls inside it:
foreach(var control in Panel1.Controls) {
if (control is Button button)
{
button.Text = "";
button.Enabled = true;
}
}
I see what you are thinking, but you cannot dynamically change the name of the variable you are trying to edit in a for loop like that.
In a for loop, it will iterate through a starting value until it reaches a stopping condition. for loops are great for when you have a data structure like a List or an Array where you can enumerate through to get or set values.
The code you have for the for loop is starting to enumerate through either an Array or List that has a name of button. To fix this, I recommend to add the buttons to an Array and then you can use a foreach loop to set the values:
foreach (Button button in buttons){
button.Enabled = true;
button.Text = "";
}
I have problem with ASP.NET and dynamic controls. I have three ASCX. One of them creates two textboxes and some labels. The second containing control created if first ASCX (two textboxes and some labels). In addiction, second control also have link button named “Add Next” which on click event adding another control (two textboxes and some labels). The third ASCX control contains many the second ASCX (amount depend on SQL result). I made simple image to clarify:
The orange box contains many controls. The red box adding many black boxes on click “ADD NEXT”.
For now I use session variable to save state during recreate. For one “red box” it is working, but if I add more “red boxes”, clicking every “ADD NEXT” adding new control with textboxes and labels to every “red box” instead of in this where was clicked button “ADD NEXT”. I suppose why it is happening. Because every “red box” refers to the same Session variable, but I don’t know how to fix it. I was trying during OnClick event passing unique ID and setting this ID as session variable name, but it wasn’t working as I expected.
Could you tell me, how to manage it? How looks the best way to recreate controls, how I can manage controls individually? If something is not clear, I will clarify. Always I was finding answers in stackoverflow, but this problem has outgrow me.
Best wishes.
(Sorry for my English, it doesn’t my native language)
My code.
Code for creating textboxes and some labels (Calculator.cs):
public string FLong
{
get
{
object o = ViewState["FLong"];
if (o == null)
return String.Empty;
return (string)o;
}
set { ViewState["FLong"] = value; }
}
public string FWide
{
get
{
object o = ViewState["FWide"];
if (o == null)
return String.Empty;
return (string)o;
}
set
{
ViewState["FWide"] = value;
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
CreateControlHierarchy();
ClearChildViewState();
}
protected virtual void CreateControlHierarchy()
{
Literal row = new Literal();
row.Text = "<div class='row surface'>";
Controls.Add(row);
//Add new TextBox;
Literal col = new Literal();
col.Text = "<div class='col-xs-4'>";
Controls.Add(col);
TextBox fLong = new TextBox();
fLong.ID = "fLong";
fLong.CssClass = "form-control";
//fLong.TextChanged += new EventHandler(Calculate_TextChanged);
//fLong.AutoPostBack = true;
fLong.Text = FLong;
Controls.Add(fLong);
Literal textLong = new Literal();
textLong.Text = "<span>ft. long x</span>";
Controls.Add(textLong);
RegularExpressionValidator flongValidate = new RegularExpressionValidator();
flongValidate.ControlToValidate = "fLong";
flongValidate.ErrorMessage = "Only Numbers allowed";
flongValidate.ValidationExpression = #"\d+";
flongValidate.ForeColor = System.Drawing.Color.Red;
flongValidate.Attributes["style"] = "display:block";
Controls.Add(flongValidate);
Literal colEnd = new Literal();
colEnd.Text = "</div>";
Controls.Add(colEnd);
//Add new Textbox
Literal col2 = new Literal();
col2.Text = "<div class='col-xs-4'>";
Controls.Add(col2);
TextBox fWide = new TextBox();
fWide.ID = "fWide";
fWide.CssClass = "form-control";
fWide.Text = FWide;
Controls.Add(fWide);
Literal textWide = new Literal();
textWide.Text = "<span>ft. wide</span>";
Controls.Add(textWide);
RegularExpressionValidator fwideValidate = new RegularExpressionValidator();
fwideValidate.ControlToValidate = "fWide";
fwideValidate.ErrorMessage = "Only Numbers allowed";
fwideValidate.ValidationExpression = #"\d+";
fwideValidate.ForeColor = System.Drawing.Color.Red;
fwideValidate.Attributes["style"] = "display:block";
Controls.Add(fwideValidate);
Literal col2End = new Literal();
col2End.Text = "</div>";
Controls.Add(col2End);
Literal rowEnd = new Literal();
rowEnd.Text = "</div>";
Controls.Add(rowEnd);
}
Code handling recreating (SurfaceCalculator.cs):
private int DefaultAmountControls = 1;
private string surfaceID;
public string SurfaceID
{
get { return surfaceID; }
set { surfaceID = value; }
}
public int Visibility
{
get
{
//store the object in session if not already stored
if (Session[surfaceID] == null)
Session[surfaceID] = DefaultAmountControls;
//return the object from session
return (int)Session[surfaceID];
}
set
{
if (value <= 5)
Session[surfaceID] = value;
else
Session[surfaceID] = 5;
}
}
protected void addSurface_Click(object sender, EventArgs e)
{
LinkButton b = (LinkButton)sender;
surfaceID = b.CommandArgument;
Visibility += 1;
}
protected override void OnInit(EventArgs e)
{
LinkButton addSurface = new LinkButton();
addSurface.Text = "+ Add surface";
addSurface.CommandArgument = surfaceID;
addSurface.Click += new EventHandler(addSurface_Click);
base.OnInit(e);
List<Calculator> c = Surface.Controls.OfType<Calculator>().ToList();
for (int i = 1; i <= Visibility; i++)
{
c.ElementAt(i - 1).Visible = true;
}
if (Visibility >= 5)
{
addSurface.Enabled = false;
}
Controls.Add(addSurface);
}
Code to adding many controls depending on SQL result
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
var listOfProjects = //GETTING FROM SQL
if(listOfProjects != null)
{
foreach (var proj in listOfProjects)
{
Panel placeHolder = new Panel();
placeHolder.CssClass = "surface";
placeHolder.ID = "placeHolder" + proj.DocumentID;
surfacesContainer.Controls.Add(placeHolder);
SurfaceCalculator newElement = (SurfaceCalculator)LoadControl("~/PATH_TO/CONTROL.ascx");
newElement.ID = "surfaceCalculator" + proj.DocumentID;
newElement.SurfaceID = newElement.ID;
placeHolder.Controls.Add(newElement);
}
}
}
I have a listview and created a textbox to search itmes in that list!
everything is ok about searching!
but problem is I want my search box to be like this:
at first Searchbox.Text="Search ..." and if user started typing in that searchbox change to that keyword! else(if) searchbox got empty Searchbox.Text change to "Search ..." again!
maybe it's a little complicated! but i tried 1-2 hours on it! and couldn't make it!
I have used Timers,checkboxchange event,booleans,...! but couldn't make it! :(
Please Help!
*my Searchbox name here is textbox1.
Some Codes I tested:
private void textBox1_TextChanged(object sender, EventArgs e)
{
string str = textBox1.Text;
/*
if (!keywordentered_bool)
{
textBox1.Text = "";
}
*/
if (str != "")
{
//Doing Search operations!
search_bool = true;
}
else
{//Doing Search operations!
search_bool = true;
// keywordentered_checkbox.Checked = true;
Searchtextbox_Timer.Interval = 100;
Searchtextbox_Timer.Enabled = true;
Searchtextbox_Timer.Tick += Searchtextbox_Timer_Tick;
//textBox2.Visible = false;
}
}
else
{
if (search_bool)
{
listView1.Items.Clear();
label1.Visible = false;
listView1.Items.AddRange(Originalplaylist_list.ToArray());
if (!search_bool)
{
listView1.Items[MusicLogindex_list[MusicLogindex_list.Count - 1]].ForeColor = Color.Cyan;
}
else if (search_bool)
{//Doing Search operations
search_bool = false;
Searchtextbox_Timer.Interval = 100;
Searchtextbox_Timer.Enabled = true;
Searchtextbox_Timer.Tick += Searchtextbox_Timer_Tick;
//textBox2.Visible = true;
// keywordentered_checkbox.Checked = false;
}
}
void Searchtextbox_Timer_Tick(object sender, EventArgs e)
{
if (!search_bool)
{
textBox2.Visible = true;
textBox2.Location = textBox1.Location;
//textBox1.Text = "Search ...";
//textBox1.ForeColor = Color.Gray;
//textBox1.Font = new Font(textBox1.Font, FontStyle.Italic);
}
else
{
textBox2.Visible = false;
// textBox1.Text = "";
// textBox1.ForeColor = Color.Black;
// textBox1.Font = new Font(textBox1.Font, FontStyle.Regular);
}
Searchtextbox_Timer.Enabled = false;
//throw new NotImplementedException();
}
This is just psuedocode but the concept is there and you need to implement the text change event for searching , you can do additional changes in event handler.
Textbox myTxtbx = new Textbox();
myTxtbx.Text = "Enter text here...";
myTxtbx.OnFocus += OnFocus.EventHandle(RemoveText);
myTxtbx.LoseFocus += LoseFocus.EventHandle(AddText);
public RemoveText(object sender, EventArgs e)
{
myTxtbx.Text = "";
}
public AddText(object sender, EventArgs e)
{
if(string.IsNullorEmpty(myTxtbx.Text))
myTxtbx.Text = "Enter text here...";
}
This is an example shows for a dynamic textbox control, you can add these events to your control and use the same code for make it work.
Or you can use this plugin
Visual Studio gallery plugin
Another plugin you can use for this purpose
Textbox with placeholder
Hope this helps.
thanks to #Frebin Francis my problem solved!
I downloaded the source code from this link TextBox With Placeholder
and added it to my project! then add it to my form and yeah! :)
i am working on an software in which i want to clear each thing after doing achieving a specific task, like clearing all the fields, list view etc etc and i've to write the a lot of things to be cleared off, like the code of my new button is:
private void btnNew_Click(object sender, EventArgs e)
{
txtProductCode1.ReadOnly = false;
txtInvoiceNo.ReadOnly = false;
cmbCustoemerType.Enabled = false;
cmbCustomerName.Enabled = false;
button1.Enabled = true;
txtProductCode1.Text = null;
txtWageName.Text = null;
txtWageCost.Text = null;
btnFirst.Visible = false;
btnPrevious.Visible = false;
btnNext.Visible = false;
btnLast.Visible = false;
cmbProductName.Enabled = true;
txtQty.ReadOnly = false;
txtPercant.ReadOnly = false;
txtDiscount.ReadOnly = false;
cmbCustoemerType.Enabled = true;
cmbCustomerName.Enabled = true;
button5.Enabled = true;
btnDelete.Enabled = true;
dtp1.Enabled = true;
btnSave.Text = "&Save";
cmbCustoemerType.Text = null;
cmbCustomerName.Text = null;
txtInvoiceNo.Clear();
txtDiscount.Clear();
txtGrandTotal.Clear();
txtProductName.Clear();
txtSalePrice.Clear();
txtQty.Clear();
txtTotal.Clear();
txtExtraWages.Text = null;
lvExtraWages.Items.Clear();
lvTransaction.Items.Clear();
lblCount.Text = null;
lblNetTotal.Text = null;
txtPercant.Text = null;
txtInvoiceNo.Text = invoice.ToString();
}
is there any way to get rid of writing the code again n again, like i need to enable one thing which i've disabled here on another button so i have to write reverse code of this to achieve the task and it's really annoying! is there any other way to do this?
EDIT:
tried following code:
private void btnNew_Click(object sender, EventArgs e)
{
//using setboxdefault function
SetTextBoxDefaults();
cmbCustoemerType.Text = null;
cmbCustomerName.Text = null;
cmbCustoemerType.Enabled = false;
cmbCustomerName.Enabled = false;
cmbProductName.Enabled = true;
cmbCustoemerType.Enabled = true;
cmbCustomerName.Enabled = true;
button5.Enabled = true;
btnDelete.Enabled = true;
button1.Enabled = true;
btnFirst.Visible = false;
btnPrevious.Visible = false;
btnNext.Visible = false;
btnLast.Visible = false;
btnSave.Text = "&Save";
lvExtraWages.Items.Clear();
lvTransaction.Items.Clear();
lblCount.Text = null;
lblNetTotal.Text = null;
dtp1.Enabled = true;
txtInvoiceNo.Text = invoice.ToString();
}
private void SetTextBoxDefaults()
{
var textBoxes = GetControls(this, typeof(TextBox));
foreach (var textBox in textBoxes)
{
TextBox.Clear();
}
}
public IEnumerable<Control> GetControls(Control control, Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetControls(ctrl, type)).Concat(controls).Where(c => c.GetType() == type);
}
but it's giving error on TextBox.Clear(); , error is Error 4
An object reference is required for the non-static field, method, or property 'System.Windows.Forms.TextBoxBase.Clear()'
Please let me know where i am mistaking..!!
As Tim has suggested, you can iterate though the controls and set each one accordingly..
public IEnumerable<Control> GetControls(Control control,Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetControls(ctrl,type)).Concat(controls).Where(c => c.GetType() == type);
}
private void btnNew_Click(object sender, EventArgs e)
{
SetComboBoxDefaults();
SetTextBoxDefaults();
SetButtonDefaults();
}
private void SetComboBoxDefaults()
{
var comboBoxes = GetControls(this, typeof(ComboBox));
foreach (var comboBox in comboBoxes)
{
((ComboBox)comboBox).Enabled = false;
((ComboBox)comboBox).Text = null;
}
}
private void SetTextBoxDefaults()
{
var textBoxes = GetControls(this, typeof(TextBox));
foreach (var textBox in textBoxes)
{
((TextBox)textBox).Clear();
}
}
private void SetButtonDefaults()
{
var buttons = GetControls(this, typeof(Button));
foreach (var button in buttons)
{
((Button)button).Visible = false;
if (button.Name == "btnSave") ((Button)button).Text = "&Save";
}
}
You can also have separate GetControl methods so that it returns a specific type of Control, reducing the need to cast to derived types.
update for edit:
You are using the TextBox type instead of the variable name in the foreach loop. Update it to use textBox (lowercase), not TextBox (pascal) see below:
private void SetTextBoxDefaults()
{
var textBoxes = GetControls(this, typeof(TextBox));
foreach (var textBox in textBoxes)
{
((TextBox)textBox).Clear();
}
}
Remember to stay DRY
Don't
Repeat
Yourself
Partition the reset logic into suitable, small methods that reset a logical grouping of controls. Then invoke those methods where and as needed.
What I have done in several such cases is this:
void SetTextBoxReadOnly(bool val, param TextBox[] textBoxes)
{
if(textBoxes != null && textBoxes.Length > 0)
{
foreach(TextBox textBox in textBoxes)
{
if(textBox != null)
{
textBox.ReadOnly = val;
}
}
}
}
void SetControlEnabled(bool val, param Control[] ctrls)
{
if(ctrls != null && ctrls.Length > 0)
{
foreach(Control ctrl in ctrls)
{
if(ctrl != null)
{
ctrl.Enabled = val;
}
}
}
}
// etc set of methods for similar situations.
// there methods can be invoked as
...
...
...
SetTextBoxReadOnly(true, txtProductCode1,
txtInvoiceNo,
txtQty,
txtPercant,
txtDiscount);
I've just started programming meaning I'm new... I've made a tic tac toe game using else if statements.
The code below is code that will reset certain values within my game, I'm sure there's but I can't find an answer - How do I shorten this block of code?
btn1.Enabled = true;
btn2.Enabled = true;
btn3.Enabled = true;
btn4.Enabled = true;
btn5.Enabled = true;
btn6.Enabled = true;
btn7.Enabled = true;
btn8.Enabled = true;
btn9.Enabled = true;
btn1.Text = "";
btn2.Text = "";
btn3.Text = "";
btn4.Text = "";
btn5.Text = "";
btn6.Text = "";
btn7.Text = "";
btn8.Text = "";
btn9.Text = "";
btn1.BackColor = default(Color);
btn2.BackColor = default(Color);
btn3.BackColor = default(Color);
btn4.BackColor = default(Color);
btn5.BackColor = default(Color);
btn6.BackColor = default(Color);
btn7.BackColor = default(Color);
btn8.BackColor = default(Color);
btn9.BackColor = default(Color);
You should use an array, or better yet, a generic list which will hold all your buttons.
For example:
List<Button> buttonList = new List<Button>();
// Add buttons to list...
buttonList.Add(btn1);
buttonList.Add(btn2);
...
Then, you can iterate on the list like this:
foreach (Button btn in buttonList)
{
btn.Text = "";
btn.BackColor = default(Color);
}
The code above will run on all the buttons in the list and for each of them clear the text and set the BackColor.
This should be done with arrays, instead of btn1, you would have btn[], and then you can access them with a for loop:
for (i=0; i<9; i++) {
btn[i].Enabled = true;
btn[i].Text = "";
btn[i].Color = default(Color);
}
and these 5 lines of code contain all the code you have above.
reset for all button at control
foreach(var item in this.Controls)
{
if (item is Button)
{
item.Enabled = true;
item.Text = "";
item.BackColor = default(Color);
}
}