I working on a project. I have text boxes and with TextChanged event I changed the text to upperCase
txt.ToUpper();
and after that the selectionStart starts at the beginning. I changed that to textbox.text.length .
how can I determine the changes? I want to move selectionStart to where the user made the change in the text.
Store the the previous text in a variable, say, previousVariable, initialized with null.
string prevVal = null;
private void txtSel_TextChanged(object sender, TextChangedEventArgs e)
{
if(prevVal == null)
{
prevVal = txtSel.Text;
}
else
{
for(int i = 0; i < txtSel.Text.length; i++)
{
if(txtSel.Text.Substring(i, 1) != prevVal.Substring(i, 1))
{
txtSel.SelectionStart = i+1;
break;
}
}
}
}
Try using the above code on selection change.
Related
I usually figure things out but this has me beat.
I have an array of listboxes on a form and a submit button. The user can pick items from any listbox then click the submit button to choose the confirm the item, but what needs to happen is that if they select something from listbox 1 then change their mind and select something from listbox 2, the item selected in listbox 1 should become unselected.
I can code that in to the eventhandlers but the problem is as soon as I change a value in another listbox programatically it fires another event. I can't seem to logic my way out of it.
Any ideas would be great otherwise I guess I will just have to put multiple submit buttons.
EDIT:
I figured out what I think is quite an obvious and simple solution in the end. I made use of the focused property to distinguish whether the user or the program was making changes. Works for both mouse and keyboard selections.
Thanks for the suggestions...
for (int i = 0; i < treatments.Length; i = i + 1)
{
this.Controls.Add(ListBoxes[i]);
this.Controls.Add(Labels[i]);
this.Controls.Add(Spinners[i]);
Labels[i].Top = vPosition - 20;
Labels[i].Left = hPosition;
Labels[i].Width = 600;
ListBoxes[i].Left = hPosition;
ListBoxes[i].Top = vPosition;
ListBoxes[i].Width = 600;
Spinners[i].Top = vPosition + ListBoxes[i].Height;
Spinners[i].Left = hPosition + ListBoxes[i].Width - 60;
Spinners[i].Width = 40;
for (int d = 25; d > 0; d = d - 1) { Spinners[i].Items.Add((d).ToString()); }
Spinners[i].SelectedIndex = 24;
//EVENT HANDLER CODE that is executed if any selectetindexchange in any LIstbox in array
ListBoxes[i].SelectedIndexChanged += (sender, e) =>
{
for (int s = 0; s < i; s = s + 1)
{
//FIND WHICH LBs[s] IS THE SENDING LISTBOX
if (ListBoxes[s] == sender && ListBoxes[s].Focused == true)
{
string msg = "sender is ListBox " + s.ToString() + "\nFocus is" + ListBoxes[s].Focused.ToString();
// MessageBox.Show(msg);
}
else if(ListBoxes[s].Focused==false)
{
ListBoxes[s].SelectedIndex = -1;
}
}
}; //end of event handler
}
I generally solve this kind of problem with a flag that lets me know that I am changing things, so my event handlers can check the flag and not take action in that case.
private int codeChangingCount = 0;
private void combobox1_SelectedIndexChanged(object sender, EventArgs e) {
codeChangingCount++;
try {
combobox2.SelectedIndex = someNewValue;
} finally {
codeChangingCount--;
}
}
private void combobox2_SelectedIndexChanged(object sender, EventArgs e) {
if (codeChangingCount == 0) {
//I know this is changing because of the user did something, not my code above
}
}
You can do this with a simple bool instead of an int, but I like the counter approach so that I can keep incrementing codeChangingCount in nested calls and not accidentally reset it. In my production code, I have a class dedicated to this kind of flagging, and it (mis)uses IDisposable to decrement, so I can just wrap my calls in a using block, but the above snippet is simpler for illustration.
Check if Focused ListBox == ListBox2 and SelectedIndex > -1 then deselect Index[0]
if (ListBoxes[s] == sender && ListBoxes[s].Focused == true)
{
if(s == 1 && ListBoxes[s].SelectedIndex > -1) //assuming 1 is listbox2
{
ListBoxes[0].SelectedIndex = -1; // Deselect ListBox1
}
string msg = "sender is ListBox " + s.ToString() + "\nFocus is" + ListBoxes[s].Focused.ToString();
}
I am trying to read Current value of Text Box in PreviewKeyDown Event but unable to get current value.
Here is my code ,
private void txtDoscountValue_PreviewKeyDown(object sender, KeyEventArgs e)
{
try
{
if (txtDoscountValue.Text == string.Empty)
discountPercentage = 0;
else
discountPercentage = float.Parse(txtDoscountValue.Text);
CalculateCart(cartItems, discountPercentage, 0);
}
catch
{ }
}
Maybe your problem is that you are asking at PreviewKeyDown, so when it gets called, there is still no values in the box. If you want to get called when the box actually changes you need to hook to KeyDown or even better TextChanged.
PreviewKeyDown is for checking the content of the change before actually applying it, which is kind of validation.
The value of the modification is stored in the keyEventArgs, not in the textbox.
It is possible to read value of TextBox at any time with Text property of TextBox control:
var currentValue=textBox.Text;
To read inputted keys of keyboard, you can use e.Key of KeyEventArgs:
private void txtDoscountValue_PreviewKeyDown(object sender, KeyEventArgs e)
{
try
{
string input=e.Key;
var ee = txtDoscountValue.Text;
}
catch { }
}
Update:
It is possible to use KeyConverter class to convert Keys to string. You should add reference to assembly System.Windows.Forms to your WPF project to use KeyConverter class:
private void textBox1_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
try
{
char c = '\0';
System.Windows.Input.Key key = e.Key;
if ((key >= Key.A) && (key <= Key.Z))
{
c = (char)((int)'a' + (int)(key - Key.A));
}
else if ((key >= Key.D0) && (key <= Key.D9))
{
c = (char)((int)'0' + (int)(key - Key.D0));
}
else if ((key >= Key.NumPad0) && (key <= Key.NumPad9))
{
c = (char)((int)'0' + (int)(key - Key.NumPad0));
}
//here your logic
}
catch { }
}
}
I m Working On A windows Form.. I Need my TextBox Not To Accept negative Values ..How Can I Do this..
IS There Any Property Availiable For Doing The same...
You need to write keypress event of textbox like :
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}
You can also user numeric updown control to prevent negetive values.
UPDATE :
Ref: Sai Kalyan Akshinthala
My code will not handle the case of copy/paste. User can enter negative values by copy/paste. So I think Sai Kalyan Akshinthala's answer is correct for that case except one small change of Length >= 2.
private void textBox1_TextChanged(object sender, EventArgs e)
{
if(textBox1.Text.Length >= 2)
{
int acceptednumber = Convert.ToInt32(textBox1.Text);
if(acceptednumber < 0)
{
textBox1.Text = "";
MessageBox.Show("-ve values are not allowed");
}
else
{
textBox1.Text = textBox1.Text;
}
}
}
yes you can do write the following code part in textchanged event of textbox
if(textBox1.Text.Length >= 2)
{
int acceptednumber = Convert.ToInt32(textBox1.Text);
if(acceptednumber < 0)
{
textBox1.Text = "";
MessageBox.Show("-ve values are not allowed");
}
else
{
textBox1.Text = textBox1.Text;
}
}
just use min and pattern will not allow to enter a minus value
min="0" pattern="^[0-9]+$" in input type
I want to add "," to after every group of 3 digits. Eg : when I type 3000000 the textbox will display 3,000,000 but the value still is 3000000.
I tried to use maskedtexbox, there is a drawback that the maskedtexbox displayed a number like _,__,__ .
Try adding this code to KeyUp event handler of your TextBox
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (!string.IsNullOrEmpty(textBox1.Text))
{
System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("en-US");
int valueBefore = Int32.Parse(textBox1.Text, System.Globalization.NumberStyles.AllowThousands);
textBox1.Text = String.Format(culture, "{0:N0}", valueBefore);
textBox1.Select(textBox1.Text.Length, 0);
}
}
Yes, it will change the value stored in a texbox, but whenever you need the actual number you can use the following line to get it from the text:
int integerValue = Int32.Parse(textBox1.Text, System.Globalization.NumberStyles.AllowThousands);
Of course do not forget to check that what the user inputs into the textbox is actually a valid integer number.
Use String.Format
int value = 300000
String.Format("{0:#,###0}", value);
// will return 300,000
http://msdn.microsoft.com/en-us/library/system.string.format.aspx
This may work fine for your scenario I hope.
private string text
{
get
{
return text;
}
set
{
try
{
string temp = string.Empty;
for (int i = 0; i < value.Length; i++)
{
int p = (int)value[i];
if (p >= 48 && p <= 57)
{
temp += value[i];
}
}
value = temp;
myTxt.Text = value;
}
catch
{
}
}
}
private void digitTextBox1_TextChanged(object sender, EventArgs e)
{
if (myTxt.Text == "")
return;
int n = myTxt.SelectionStart;
decimal text = Convert.ToDecimal(myTxt.Text);
myTxt.Text = String.Format("{0:#,###0}", text);
myTxt.SelectionStart = n + 1;
}
Here, myTxt = your Textbox. Set Textchanged event as given below and create a property text as in the post.
Hope it helps.
You could hook up to OnKeyUp event like this:
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (!(e.KeyCode == Keys.Back))
{
string text = textBox1.Text.Replace(",", "");
if (text.Length % 3 == 0)
{
textBox1.Text += ",";
textBox1.SelectionStart = textBox1.Text.Length;
}
}
}
Get Decimal Value Then set
DecimalValue.ToString("#,#");
I have a check list box control and I want to select only one item at a time and I am currently using this code to do the same.
private void CLSTVariable_ItemCheck(object sender, ItemCheckEventArgs e)
{
// Local variable
int ListIndex;
CLSTVariable.ItemCheck -= CLSTVariable_ItemCheck;
for (ListIndex = 0;
ListIndex < CLSTVariable.Items.Count;
ListIndex++)
{
// Unchecked all items that is not currently selected
if (CLSTVariable.SelectedIndex != ListIndex)
{
// set item as unchecked
CLSTVariable.SetItemChecked(ListIndex, false);
} // if
else
{
// set selected item as checked
CLSTVariable.SetItemChecked(ListIndex, true);
}
} // for
CLSTVariable.ItemCheck += CLSTVariable_ItemCheck;
}
this code is working fine.
but problem is that when I click again and again on selected item then that selected item should not be unchecked, means at least one item should be checked always...
I agree with commentators above - you should consider using radiobuttons. But if you really need CheckedListBox, then use this ItemChecked event handler instead:
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (checkedListBox1.CheckedItems.Count == 1)
{
Boolean isCheckedItemBeingUnchecked = (e.CurrentValue == CheckState.Checked);
if (isCheckedItemBeingUnchecked)
{
e.NewValue = CheckState.Checked;
}
else
{
Int32 checkedItemIndex = checkedListBox1.CheckedIndices[0];
checkedListBox1.ItemCheck -= checkedListBox1_ItemCheck;
checkedListBox1.SetItemChecked(checkedItemIndex, false);
checkedListBox1.ItemCheck += checkedListBox1_ItemCheck;
}
return;
}
}
Well, it was an answer to me! I couldn't get the above code to work in the checkedListBox1_ItemCheck. I had to modify a portion of it ans include it in the checkedListBox1_SelectedIndexChanged event. But I couldn't remove the original code all together. Here is what I've added...
private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (checkedListBox1.CheckedItems.Count > 1)
{
Int32 checkedItemIndex = checkedListBox1.CheckedIndices[0];
checkedListBox1.ItemCheck -= checkedListBox1_ItemCheck;
checkedListBox1.SetItemChecked(checkedItemIndex, false);
checkedListBox1.ItemCheck += checkedListBox1_ItemCheck;
}
}
Which is basically, if you have more than 1 box checked, switch the last one for the new one. I'm curious why the original code didn't work. And why it has to be there for my new code to work? Thank you.
I found this code it work so well
private void chkboxmov_ItemCheck(object sender, ItemCheckEventArgs e)
{
for (int ix = 0; ix < chkboxmov.Items.Count; ++ix)
if (ix != e.Index)
chkboxmov.SetItemChecked(ix, false);
}
"at least one item should be checked always"
The current solution (the last one) allows items to be checked off. If your purpose is to select exactly one item at all times, use this as a MouseUp event,
private void ChklbBatchType_MouseUp(object sender, MouseEventArgs e)
{
int index = ((CheckedListBox)sender).SelectedIndex;
for (int ix = 0; ix < ((CheckedListBox)sender).Items.Count; ++ix)
if (index != ix) { ((CheckedListBox)sender).SetItemChecked(ix, false); }
else ((CheckedListBox)sender).SetItemChecked(ix, true);
}