Custom Control - How to Draw Textbox on combobox - c#

I'm developing Win Form Application
In my UI, I have to make ComboBox which should be dropdown only at first but after selecting any item, it should be partially editable.
E.G.
Options are like,
Item Value - 10
Item Value - 20
Item Value - 30 etc.
Now, if Item Value - 20 is selected, number 20 should be editable (20-29 of course)
But here editing should be allowed only to change numeric value, not Text part.
and also only numeric part should be selected to make it more user friendly.
If there may some internal properties in ComboBox to do so (which I guess will not be the case), it will be straight forward way.
Else to do so, I was thinking of having a TextBox drawn/placed on ComboCox accurately.
In this approach I'm not clear how to put TextBox so accurately that my custom user control looks like single unit and it don't overlap "text" part of combobox ?

I don’t think the combo box control was intended to be used in this way as a simple validated text box seems to be a better control for you and the user if they must enter data. Granted, you could simply add all the numbers you need into the combo box, but the user would have to scroll to the number they wanted. If this list is large then it won’t be very user friendly. The problem with the user typing something into the combo box is a matter of what to do when the user finishes typing. Even with suggestions on, when the user finishes typing something into the combo box, nothing happens until the user presses the Enter key.
If the user typed something that matches one of the items in the list then presses the Enter key, the combo boxes SelectedIndexChanged event will get fired. However, if the user types something that is NOT currently in the items list and presses the Enter key the SelectedIndexChanged event will NOT get fired.
Using the combo box KeyDown event, you could capture the “EnterKey” when the user presses the enter key in the combo box, as this is something the user would do anyway to select an existing item. So when the user types something that already exist in the list and presses the Enter key BOTH SelectedIndexChanged AND KeyDown events get fired in that order. If the user types something that is NOT in the items list, then only the KeyDown event gets fired.
Using the KeyDown event a check is made on what the selected value is. If the item typed by the user is in the items list then we can ignore these as they were handled in the previous call to SelectedIndexChanged. When the user typed something new, obviously you would possibly need to check the range of the values then simply call your method with the users input.
Again this seems hacky and IMHO, a validated text box would be easier on you and simple for the user especially if they have to type it anyway.
List<string> comboData;
public Form1() {
InitializeComponent();
comboData = new List<string>();
for (int i = 1; i < 100; i++) {
comboData.Add(i.ToString());
}
comboBox1.DataSource = comboData;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
MessageBox.Show("selection changed " + comboBox1.Text);
}
private void comboBox1_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.Enter) {
if (comboData.Contains(comboBox1.Text.ToString())) {
MessageBox.Show("User entered existing data: " + comboBox1.Text);
// selection changed event has already handled this, however
// if the user just pressed "enter" previously
// then selection changed event wont get fired because the selection did not change
}
else {
MessageBox.Show("User entered NEW data: " + comboBox1.Text);
// we have data that is NOT currently in the list
// so selection changed WONT get fired
// need to call your method with user typed value
}
}
}
// make user user only enters numbers
private void comboBox1_KeyPress(object sender, KeyPressEventArgs e) {
if (!Char.IsNumber(e.KeyChar)) {
e.Handled = true;
}
}
Note: I cannot tell what exactly what your combo items list contains. If there is text in the items like “Item Value –”... this seems unnecessary. In the code above I simply used the needed info i.e... the numbers in the combo box items list. Also I used a key press event to filter out unwanted alpha characters.
Hope this helps.

Related

Autopopulate text box based on Radio Button checked in C#?

I'm just curious if there is an easy way to have my text box auto populate a string depending on whether a radio button is clicked.
For example, I have three radio buttons: residential, commercial, industrial
and I have a text box called txtCustomerType
I'm using the input from txtCustomerType to log the info to a list, but right now the user has to manually add R,C or I. The radio buttons are being used for the charge calculation (it's a little program that has different rates depending on customer)
You can use event handlers for this.
Under properties for the item you want, you'll find event handlers here:
Then just double click the event you want, and all the necessary stuff will be automatically created for you.
And here is where you want to write the code what happens when e.g. the checked status changes:
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
if (radioButton1.Checked)
textBox1.Text = "Radio button 1 checked";
}

ComboBox open while another control has focus

I have a case where the user is given a ComboBox with potentially a lot of choices in it. Paired with this is a TextBox that filters the items. What I would like to do is open the drop down list when the TextBox has focus--let the user see what the current filter accomplishes as they type it. (This isn't just autocomplete, I'm currently matching the filter text anywhere in the item, I may replace this with a RegEx search down the road.)
It sounds simple enough--drop the box when the TextBox gets focus, close it when it loses focus. It opens--and promptly closes back up. Any good answers?
My Google-Fu must be weak tonight, I can't believe nobody has wanted to do this before yet I find nothing out there. (I have seen a related thing of typing in an open ComboBox to provide suggested options like Google does but my list is required, not merely suggestions.)
You can add on the Focus event of the TextBox code for the ComboBox setting the property
ComboBox.DroppedDown = true;
Than add on the TextChanged event of the TextBox code
ComboBox.SuspentLayout();
//ComboBox.Items add/remove
ComboBox.ResumeLayout();
Don't forget to reset the items when Text is empty.
EDIT:
This seems to work (but you don't get to see the mouse)
string[] items = { "abcd", "abc", "bcd", "cd" };
private void textBox1_TextChanged(object sender, EventArgs e)
{
comboBox1.SuspendLayout();
comboBox1.Items.Clear();
comboBox1.Items.AddRange(items.Where(item => item.ToLower().Contains(textBox1.Text.ToLower())).ToArray());
comboBox1.ResumeLayout();
comboBox1.DroppedDown = true;
}

Deselect text in DataGridViewTextBoxCell after .CommitEdit(DataGridViewDataErrorContexts.Commit)

Sometimes while the user is typing text in a DataGridViewTextBox you want to enable or disable a control, depending on the value being typed. For instance enable a button after you typed a correct value
Microsoft showed the way in an article about how to create a DataGridViewButtonCell that can be disabled.
This is their trick (it can also be seen in other solutions)
Make sure you get the event DataGridView.CurrentCellDirtyStateChanged
Upon receipt of this event, commit the changes in the current cell by calling:
DataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
This commit will lead to the event DataGridView.CellValueChanged
Make sure you get notified when this event is raised
In your OnCellValueChanged function, check the validity of the changed value and decide
whether to enable or disable the corresponding control (e.g. button).
This works fine, except that the CommitEdit makes that the text is selected while in OnCellValueChanged. So if you want to type 64, you get notified when you type 6 and later when you type 4. But because the 6 is selected you don't get 64, but the 6 is replaced by 4.
Somehow the code must deselect the 6 in OnCellValueChanged before interpreting the value.
The property DataGridView.Selected doesn't do the trick, it doesn't deselect the text, but it deselects the cell.
So: how to deselect the text in the selected cell?
I think you need something that when the user is typing some text into the current cell, you need to know the current text (even before committing it) to check if some button need to be disabled. So the following approach should work for you. You don't need commit any thing, just handle the TextChanged event of the current editing control, the editing control is exposed only in the EditingControlShowing event handler, here is the code:
//The EditingControlShowing event handler for your dataGridView1
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e){
var control = e.Control as TextBox;
if(control != null &&
dataGridView1.CurrentCell.OwningColumn.Name == "Interested Column Name"){
control.TextChanged -= textChanged_Handler;
control.TextChanged += textChanged_Handler;
}
}
private void textChanged_Handler(object sender, EventArsg e){
var control = sender as Control;
if(control.Text == "interested value") {
//disable your button here
someButton.Enabled = false;
//do other stuff...
} else {
someButton.Enabled = true;
//do other stuff...
}
}
Note that the conditions I used above can be modified accordingly to your want, it's up to you.

Detect if mouse click hits a item not in listbox [C#]

If the user click on a item in the listbox, the listboxItems_SelectedIndexChanged is called. But, even if the user miss an item and randomly clicks inside the listbox (not on items) the listboxItems_SelectedIndexChanged is still called.
How can I change this? I only want action on item click.
Note: removing the ability to navigate the application with keyboard is not a option.
I guess that in some cases you don't have enough list items in your control, therefore you have some space that you can click on and then SelectedIndexChanged is fired.
I guess you cannot dynamically resize the control to always fit the number of list items or else you wouldn't be asking this question.
Now, what should happen when the user click (selects) the same list item? Should some logic happen even though the selected index is the same (so when it was clicked the first time the same logic happend)?
If you require that selecting the same index more than once should be ignored then you could use the following hack:
Keep a variable at the form scope (the form containing the listbox control) and each time the selection index changes set that variable. Then use it later to check if the same selection has been made to ignore handling the event. Here is an example:
private int _currSelIdx = -1; // Default value for the selected index when no selection
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listBox1.SelectedIndex == _currSelIdx)
return;
Console.WriteLine(listBox1.SelectedIndex);
_currSelIdx = listBox1.SelectedIndex;
}
It ain't pretty, but hey...whatever works!
Maybe SelectedIndexChanged is not the right place to put your logic, since it is triggered even when you change the selection with the keyboard.
I would use MouseClick instead, checking if the click occurred over the selected item, i.e. something like this:
private void listBox1_MouseClick(object sender, MouseEventArgs e)
{
if (listBox1.SelectedIndex < 0 || !listBox1.GetItemRectangle(listBox1.SelectedIndex).Contains(e.Location))
MessageBox.Show("no click");
else
MessageBox.Show("click on item " + listBox1.SelectedIndex.ToString());
}
This link may help, instead of double click, implement the same for single click
i want to detect an item double click in a winforms listbox control. [how to handle click on blank area?]

WinForms: two way TextBox problem

I have a TextBox, which I use for both data input and display. A user can select items from a list and for each item there is a corresponding text which is displayed in the TextBox when the item is selected.
The user can edit this textbox, thus changing the list item's correponding text.
My problem is this: I use the TextChanged event to detect when the user enters some text and I update the internal variables in the event handler, however this event handler is called when I programmatically change the values of the textbox too. I want this handler only to be called when the User changes the textbox. How can I achieve this?
edit: I have the same problem a combo box as well.
The handler will always be called - no way disable it that I'm aware of. However you can simply set a flag in your class to indicate the you've programatically changed the state and should ignore the next event.
_updating = true;
_textBox.Text = "New Text";
...
_textBox_TextChanged( object sender, EventArgs e )
{
if( _updating ) { _updating = false; return; }
// Do something special with the new text.
}
You might also try creating your textbox control and overriding the Text property to provide your own custom logic.
class MyTextBox : TextBox
{
public overrides string Text{
get{ return base.Text; }
set{
if( value == Text ) return;
_updating = true;
base.Text = value;
_updating = false;
}
}
}
The TextChanged event is invoked whenever the TextBox changes its Text property, which can be achieved via modifying the Text property, or when the user directly changes the text, there are other events which are more likely usable for the scenario you are trying to achieve.
KeyPress: Raised whenever the user pulses a key
KeyDown: Raised whenever a Key is pulled down
KeyUp: Raised whenever a Key is pulled up (released)
Hope it helps
You could set a flag in the programatic updates, and in the event handler exit early if the flag is set.
But if you use databinding, then the variables and the gui are synchronized automatically, which avoids this problem all together.
Do you mean you want the second textbox to display something which depends on what's in the first textbox, but ONLY if the user did set it ?
Could you be more specific about what you are trying to achieve? It seems to me that your UI design may be confusing for the user, since the text in B is sometimes related to A, and sometimes not.
If you still want to do it, the typical way to go is to use an updating flag, as proposed in other answers.
Check for focus on the textbox. If it does not have focus, it means the user isn't editing it.

Categories

Resources