I'm building a form for searching a database inside my application, and I only want to add a control's input as a WHERE if its enabled. The best method I have found is a set of checkboxes next to each set of controls to enable them.
Now, I can add the logic to the CheckedChanged of each checkbox, but I have several different types of controls- textboxes, datepickers, comboboxes. So they would have to be done individually- leading to quite a bit of boilerplate code.
private void ChartCheckBox_CheckedChanged(object sender, EventArgs e)
{
ClassComboBox.Enabled = ChartCheckBox.Checked;
}
Is there a faster way to do this?
I'd do this using a composite control - it's exactly what you need.
Why don't you just include a particular field's WHERE clause if the length of the text in that field is > 0? e.g. if (txtArtist.Text.Length > 0) { ...
That way you can get rid of the check boxes and the form will be more self-maintaining...
Related
Here is what I have tried and is working. But I want to whether this is proper or is there a better option or way to do the same
private void tabs_SelectedIndexChanged(object sender, EventArgs e)
{
TabControl control = (TabControl)sender;
if(control.SelectedIndex == 3 || control.SelectedIndex == 0)
{
button1.Parent = control.SelectedTab;
zonalarealabel.Parent = control.SelectedTab;
pictureBox3.Parent = control.SelectedTab;
}
}
If you don't mind coupling your code to your user interface then your approach is valid. However, I think the better option is to create a user control that raises events handled by the selected tab. The user control would appear on tabs 0 and 3 at all times. The advantage of this is that you don't need to modify your SelectedIndexChanged event handler should you want these buttons to appear on a future tab. There are many ways to approach this problem, but given the very narrow functional requirements you shared, it's a better design to relegate these buttons to a user control rather than re-parent them at runtime.
What is the best way to create and read multiple textboxes in a windows form? In my application, I have a windows form where customer can enter multiple addresses, email addresses
Right now I have a form like this,
TextBoxAddress1 TextBoxEmail1
TextBoxAddress2 TextBoxEmail2
.....
.....
.....
TextBoxAddressN TextBoxEmailN
For this I dragged and dropped multiple controls on a form and named each one of them.
If I use this method I had to write lengthy code to see if first row (TextBoxAddress1 TextBoxEmail1) is filled for validation and even for reading I had to write many lines of code.
Is there a better to way achieve this?
You can use the following code to add a TextBox dynamically to your form:
private int m_CurrTexboxYPos = 10;
private List<TextBox> m_TextBoxList = new List<TextBox>();
private void CreateCheckBox()
{
m_CurrTexboxYPos += 25;
TextBox textbox = new TextBox();
textbox.Location = new System.Drawing.Point(0, m_CurrTexboxYPos);
textbox.Size = new System.Drawing.Size(100,20);
Controls.Add(textbox);
m_TextBoxList.Add(textbox);
}
I would have a listbox/listview with your emails and Add/Edit/Delete buttons which show a popup form - the logic for validating emails, etc. would then be in the one place and your list can grow without you ever needing to add controls to the form.
You could dynamically create textboxes - but you end up writing code to make sure they layout nicely on the form, etc. - having some type of list is easier IMO and also lends itself to binding (e.g. to an email object)
Dynamically adding controls is pretty simple, provided you can use DockStyle and an exclusive container for them (e.g. a Panel). If you can't use DockStyle, then you need to write logic to determine Location and Size (which isn't fun).
On a simple form, I have two buttons and a panel, Button1 adds a new TextBox to Panel1, Button2 iterates through the controls in Panel1 and then checks that they are the correct type or throws an exception. This is where you you would put validation or reading logic. Panel1 needs to have AutoScroll = true; otherwise you will run controls off of the viewable screen.
This concept can be switched for anything that inherits from UserControl (all .Net native controls or your own custom controls).
private void button1_Click(object sender, EventArgs e)
{
TextBox NewEmailBox = new TextBox();
NewEmailBox.Name = "NewEmailBox" + this.panel1.Controls.Count;
NewEmailBox.Dock = DockStyle.Top;
this.panel1.Controls.Add(NewEmailBox);
}
private void button2_Click(object sender, EventArgs e)
{
foreach (Control item in this.panel1.Controls)
{
if (item is TextBox)
{
//Do your reading/validating here.
}
else
{
throw new InvalidCastException(string.Format("{0} was in Panel1 and is of type {1} not TextBox!", item.Name, item.GetType()));
}
}
}
Write a user control for each of the groupings you need. at least one One for address, one for email etc. then all of your validation, calls to your database access is contained in a single location
That is just good design. this way if you have multiple tabs for things like Home Information, Work Information, Emergency Contact Information, you can just place them on the form. This is pretty common for a user profile.
Then a listview for each grouping on a user profile page or whatever, that has edit/delete/add then popup a dialog with the appropriate user control in it.
Most simply, ListBox adove TextBox with Button.
Also you can use DataGridView, BuiltIn functionality for Add\Edit\Delete.
Here using DataGridView (ShowHeader set to false, EditMode to On Enter, with one Column with AutoSizeMode in Fill property)
The less of repeatable code you have, the better programmer you are.
Whenever you see a pattern (something what is repeatable), you could and you should try to optimize it. Unless it's something too small to worry.
In your case, determine first what is the basic of repeatable thing. Do you always have to enter address and email address? Then combine them into a control, which can carry out validation. Do you have to use this control often (or repeat N times)? Then maybe it make sense to switch to a list instead (ListBox, ListView or DataGridView).
Are you too lazy to bother configuring things? Then just optimize something what is obviously going to repeat: put validation into common method and call it from each TextBox event. Or make own TextBox with method build-in. Or do validation at once in the Ok button event by using loop.. or not by using loop.
To find best method you have to first decide best for who. Because customer want something shiny,easy to use, animated, with cats and boobs.. ok, without cats and boobs. The point is: how much work are you willing to put to have it best for the customer.
If I would have to enter table data (or data which form table), I'd go with DataGridView so it would looks like this.. or better:
Actually on a WinForms project (VS 2010, C#, .NET 4.5), I build a matrix (10x10) in a form. Each element is represented by a control that can be "checked" or "unchecked". Each element's state is completely independent of another.
The ideal solution would be to use a CheckBox. Unfortunately, the client wants a different appearance - for example, the one of the RadioButton. I could use RadioButton, place every one of them in a dedicated group, add an event listener to uncheck on-click if the element is already checked... Pretty much for a question of appearance!
Couldn't I override some rendering methods of CheckBox class? (Anyway, that's the only place in the whole application where I use this control)
Note: Controls are instanciated on runtime from a class MyClass:CheckBox.
Use a RadioButton if you need to make it look like one. You'll need to set their AutoCheck property to False to make them act like check boxes and give them a common event handler:
private void radioButtons_Click(object sender, EventArgs e) {
var button = (RadioButton)sender;
button.Checked = !button.Checked;
}
Never hesitate to point out that this is very poor UI design.
I was just wondering if anyone has come across how to apply an input mask for a Tool Strip Combo Box in C#?
My drop down box gets populated over time with IP addresses, and I would like to restrict what the users are able to write in (Ex: can only input 3 '.'s, only numbers, etc).
So if anyone is able to help out I would really appreciate it!
Thanks in advance.
Edit
My design has changed so I now need to have a ToolStripComboBox
You could try catching the KeyUp event, then check that the input is valid. If not revert it to the last valid input. You would probably want to do something similar with the Validating event (make sure CausesValidation is true).
Another option would be to create a MaskedTextBox and place it so it covers the text box portion of the drop down menu. You would then need to wire up the events so the two form controls remained synced.
You could also look into the ErrorProvider class.
There are a couple of other ways (like a timer which runs ever .3 seconds), but those are usually performance hogs or difficult to maintain.
Update for regular expression comment:
If I was to do this I might use a regular expression or I might manually parse the string.
Either way the KeyUp and Validating events is where I would check the validation of the control. The KeyUp event gives me the option to check as they type while the Validating event allows me to validate when the control loses focus. Which you use will depend on what you want the user experience to be.
If you do not use the KeyUp event to validate, you could add a timer which runs 5 seconds after the last key press. This way the control would not have to lose focus for the error to show.
Update for edited question and comment:
You could not use Format event as your question was on how to format user input, not how things are added to the list. As such that solution does not work with ToolStripComboBox or with ComboBox.
After reading the documentation for ToolStripControlHost, you might be able to cast ToolStripComboBox to ComboBox. If not then you could use the ToolStripControlHost to place the ComboBox onto your form. - This is incorrect or unnecessary, please see update below the quote.
ToolStripControlHost is the abstract base class for ToolStripComboBox, ToolStripTextBox, and ToolStripProgressBar. ToolStripControlHost can host other controls, including custom controls, in two ways:
Construct a ToolStripControlHost with a class that derives from Control. To fully access the hosted control and properties, you must cast the Control property back to the actual class it represents.
Extend ToolStripControlHost, and in the inherited class's default constructor, call the base class constructor passing a class that derives from Control. This option lets you wrap common control methods and properties for easy access in a ToolStrip.
Use the ToolStripControlHost class to host your customized controls or any other Windows Forms control.
To customize a ToolStripItem, derive from ToolStripControlHost and create a custom implementation. You can override methods such as OnSubscribeControlEvents to handle events raised by the hosted controls, and you can put custom functionality into properties to enhance the hosted control.
Update:
According to the ToolStripComboBox documentation you can access the underlying ComboBox through ToolStripComboBox's ComboBox property.
This is why I usually read the documentation on a control before I use it. I might not understand it, but at least I will have an idea what to look for. :)
You should create Format event like this:
private void comboBox1_Format(object sender, ListControlConvertEventArgs e)
{
e.Value = GetFullIpFormat((string)e.Value);
}
And here is code for formating values:
string GetFullIpFormat(string value)
{
string[] ip = new string[4];
for (int i = 0; i < ip.Length; i++)
{
ip[i] = GetIpPart(i, value);
}
return string.Format("{0:###}.{1:###}.{2:###}.{3:###}", ip[0], ip[1], ip[2], ip[3]);
}
string GetIpPart(int partNumber, string ip)
{
string result = "000";
int iLen = 3;
ip = ip.Replace(".", "");
int iStart = partNumber * iLen;
if (ip.Length > iStart)
{
result = ip.Substring(iStart);
if (result.Length > iLen)
{
result = result.Substring(0, iLen);
}
}
return result;
}
This will do formating for you.
Alternativly you can check input on same event for numbers.
This will do the job for you, happy coding! :)
I have a web form where I register a new employee. There're 3 parts in the form: Personal info, Address info, Special Status. But there's only one button for the whole form. When I submit the form all the information is updated to the database. So three Update statements are executed against the database. The methods are UpdatePersonalInfo, UpdateAddressInfo and UpdateSpStatus. Is there a way to check if there's been a change in any field in the certain part and run update method only if it's true. So something like this:
if (There's been any change to the personal data of the employee)
{
UpdatePersonalInfo;
}
if (There's been any change to the address information of the employee)
{
UpdateAddressInfo;
}
Sure I know, I can save all the previous values in a session object in PageLoad and then compare them one by one before running the method. But I thought maybe there's a magic way of doing this more easily.
Not sure that this is a better solution than any of the alternatives you already mentioned, but you could create a default handler to attach to the TextChanged, SelectedIndexChanged, etc events of your controls to keep track of which ones have changed.
List ChangedControls = new List(Of, String);
private void ChangedValue(object sender, System.EventArgs e) {
WebControl cntrl = (WebControl) sender;
ChangedControls.Add(cntrl.ID);
}
Then on your button click scour the ChangedControls list for the relevant controls.