I am developing one Windows phone app. In my app I want to get the latest entered word in textbox not the last word. And I want to change that latest entered word on space key pressed. I am getting the last word on a key up event like this:
private async void mytxt_KeyUp_1(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Space || e.Key == Windows.System.VirtualKey.Enter)
{
if (string.IsNullOrWhiteSpace(textBox_string) == false)
{
string[] last_words = Regex.Split(textBox_string, #"\s+");
int i = last_words.Count();
last_words = last_words.Where(x => x != last_words[i-1]).ToArray(); last_word = last_words[last_words.Count() - 1];
last_word = last_word.TrimStart();
}
}
}
I am getting the last word by this method but actually I want to get latest entered word by user. Meaning, if the user moves the cursor directly to the middle of textbox and types any word then I want to get that word on space key pressed event; I want the position of that word and can change that word programmatically and update textbox.
For example, if the user types
H!! my name vanani
but then the user moves the cursor directly after 'name' and types 'is sohan'
H!! my name is sohan
then I want to get word and position of 'is' and same for 'sohan' in key up event of textbox. I need the position to replace that word with another word and update textbox with the new replaced text.
I have seen these questions. winforms - get last word.. and C# how to get latest char.. but they didn't help me. Please help me.
Like this:
if (Regex.IsMatch(textBox_string, #"\S*(?=\s?$)"))
{
Match match = Regex.Match(textBox_string, #"\S*(?=\s?$)");
string word = match.Value;
int startingIndex = match.Index;
int length = word.Length;
}
I founded answer to my question.
Here is code worked for me.
Bool isFirst = false;
int mytempindex;
private async void mytxt_KeyUp_1(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Space)
{
int i = mytxt.SelectionStart;
if (i < mytxt.Text.Length)
{
if (isfirst == false)
{
mytempindex = mytxt.SelectionStart;
isfirst = true;
}
else
{
int mycurrent_index = mytxt.SelectionStart;
int templength_index = mycurrent_index - mytempindex;
string word = mytxt.Text.Substring(mytempindex, templength_index); //It is the latest entered word.
//work with your last word.
}
}
}
}
I don't think it work in all situation but through this you can get idea about how to get latest entered word from Textbox or RichTextbox.
Related
I am trying to create a text input field with autocomplete functionality. The list of available options is huge (50,000+) and will need to be queried on TextChanged (after the first 3 characters have been entered).
I have a 99%-working solution with TextBox, setting AutoCompleteCustomSource to my new AutoCompleteStringCollection in the TextChanged event, but that results in occasional memory access violations due to a well-documented bug in the underlying AutoComplete implementation...
Microsoft Support say "Do not modify the AutoComplete candidate list dynamically during key events"...
Several SO threads: 1, 2, 3
These threads have some suggestions on how to prevent the exceptions but nothing seems to completely eliminate them, so I'm looking for an alternative. have tried switching to a ComboBox-based solution but can't get it to behave as I want.
After the user types the third character, I update the ComboBox's DataSource but the first item is automatically selected. The user is not able to continue typing the rest of the name.
The ComboBox items are not visible until the user clicks the triangle to expand the list
If the user selects the text they have entered and starts typing, I set DataSource to null to remove the list of suggestions. Doing this puts the cursor at the start of the text, so their characters appear in completely the wrong order!
My View:
public event EventHandler SearchTextChanged;
public event EventHandler InstrumentSelected;
public Instrument CurrentInstrument
{
get { return comboBoxQuickSearch.SelectedItem as Instrument; }
}
public IEnumerable<Instrument> Suggestions
{
get { return comboBoxQuickSearch.DataSource as IEnumerable<Instrument>; }
set
{
comboBoxQuickSearch.DataSource = value;
comboBoxQuickSearch.DisplayMember = "Name";
}
}
public string SearchText
{
get { return comboBoxQuickSearch.Text; }
}
private void comboBoxQuickSearch_TextChanged(object sender, EventArgs e)
{
if (SearchTextChanged != null)
{
SearchTextChanged(sender, e);
}
}
private void comboBoxQuickSearch_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && InstrumentSelected != null)
{
InstrumentSelected(sender, e);
}
}
My Presenter:
private void SearchTextChanged(object sender, EventArgs e)
{
lock (searchLock)
{
// Do not update list of suggestions if:
// 1) an instrument has already been selected
// (the user may be scrolling through suggestion list)
// 2) a search has taken place within the last MIN_SEARCH_INTERVAL
if (DateTime.Now - quickSearchTimeStamp < minimumSearchInterval
|| (view.Suggestions != null && view.Suggestions.Any(i => i.Name == view.SearchText)))
{
return;
}
string searchText = view.SearchText.Trim();
if (searchText.Length < SEARCH_PREFIX_LENGTH)
{
// Do not show suggestions
view.Suggestions = null;
searchAgain = false;
}
// If the prefix has been entered or changed,
// or another search is needed to display the full sublist
else if (searchText.Length == SEARCH_PREFIX_LENGTH
|| searchText.Substring(0, SEARCH_PREFIX_LENGTH) != searchTextPrefix
|| searchAgain)
{
// Record the current time and prefix
quickSearchTimeStamp = DateTime.Now;
searchTextPrefix = searchText.Substring(0, SEARCH_PREFIX_LENGTH);
// Query matches from DB
IList<Instrument> matches = QueryMatches(searchText);
// Update suggestions
view.Suggestions = matches;
// If a large number of results was received, search again on the next chararacter
// This ensures the full match list is presented
searchAgain = matches.Count() > MAX_RESULTS;
}
}
}
(The searchAgain bit is left over from the TextBox implementation, where the AutoCompleteCustomSource wouldn't always show the complete list if it contained too many items.)
Can I get the ComboBox to work as I want it to, providing suggestions as the user types, given my requirement to query those suggestions on TextChanged?
Is there some other combination of controls I should use for a better user experience, e.g. ListBox?
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to prevent richTextBox to paste images within it?
If you're using Richtextbox, there are several advantages in Richtextbox for example:
we can use color font on it
Setting custom font in a region
Attach files on it.. etc
take a look at the picture:
Here is my problem:
Can i just make it text only?
In my project, attach file or the like is unnecessary at all. I even didn't want attach or paste an images on it, i just want "text only" on Richtextbox
How can i do that?
Since RichTextBox doesn't have a Images or Objects collection you have to go for the RTF formatting codes. All data of RichTextBox is stored as plain text with special formatting codes, this is exposed by the control through its RTF property. Learning this code language is essential if you want to read or change it, learning resources are easily available throughout the web, see for example this overview. RichTextBox uses more simplified rtf codes than several full-feature editors like MS Word etc, so it is usually beneficial to load data into a RTB before manipulating it, this will remove much redundant data.
Making a long story short, I found that it is necessary to search for rtf groups that start with either "pict" or "object" command. Knowing that groups may be nested you can't just find the first end-group char from there, you have to parse the string char by char while keeping count of grouping to find the end of those groups. Now you have enough information to remove that part of the string. Rtf may contain multiple picture/object groups so you have to do this until all are removed. Here is a sample function that return rtf string after removing those groups:
private string removeRtfObjects(string rtf)
{
//removing {\pict or {\object groups
string pattern = "\\{\\\\pict|\\{\\\\object";
Match m = Regex.Match(rtf, pattern);
while (m.Success) {
int count = 1;
for (int i = m.Index + 2; i <= rtf.Length; i++) {
//start group
if (rtf(i) == '{') {
count += 1;
//end group
} else if (rtf(i) == '}') {
count -= 1;
}
//found end of pict/object group
if (count == 0) {
rtf = rtf.Remove(m.Index, i - m.Index + 1);
break; // TODO: might not be correct. Was : Exit For
}
}
m = Regex.Match(rtf, pattern);
//go again
}
return rtf;
}
When should this be done? You have already mention Paste, there is also Insert, these can be trapped with the KeyDown event where you get the clipboard info and handle it accordingly. Setting e.Handled=True when you have handled the operation yourself signals that the control should not do any default processing for this key combination. This is also how you block pasting images without destroying the users clipboard. Example:
private void RichTextBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
//aware of Paste or Insert
if (e.Control && e.KeyCode == Keys.V || e.Shift && e.KeyCode == Keys.I) {
if (Clipboard.ContainsImage || Clipboard.ContainsFileDropList) {
//some images are transferred as filedrops
e.Handled = true;
//stops here
} else if (Clipboard.ContainsData(DataFormats.Rtf)) {
RichTextBox rtbox = new RichTextBox();
//use a temp box to validate/simplify
rtbox.Rtf = Clipboard.GetData(DataFormats.Rtf);
this.RichTextBox1.SelectedRtf = this.removeRtfObjects(rtbox.Rtf);
rtbox.Dispose();
e.Handled = true;
}
}
}
Yes, it is possible.
Handle Ctrl+V in RichTextBox1_KeyDown, then check the data format in the Clipboard: if data is plain text, paste it; if data is RTF, convert it to plain text (in a buffer without changing the Clipboard content) and paste it; don't paste any other type of data.
This is a partial example just to show you how to proceed:
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.V)
{
// suspend layout to avoid blinking
richTextBox2.SuspendLayout();
// get insertion point
int insPt = richTextBox2.SelectionStart;
// preserve text from after insertion pont to end of RTF content
string postRTFContent = richTextBox2.Text.Substring(insPt);
// remove the content after the insertion point
richTextBox2.Text = richTextBox2.Text.Substring(0, insPt);
// add the clipboard content and then the preserved postRTF content
richTextBox2.Text += (string)Clipboard.GetData("Text") + postRTFContent;
// adjust the insertion point to just after the inserted text
richTextBox2.SelectionStart = richTextBox2.TextLength - postRTFContent.Length;
// restore layout
richTextBox2.ResumeLayout();
// cancel the paste
e.Handled = true;
}
}
I have a ListBox control populated with branches of a large retail chain. The staff using the system have to log in to the relevant branch, and I would like them to be able to search the ListBox to find their branch.
I have created an event handler for when text in the search box changes, and attempted to use code sound on StackOverflow already:
private int lastMatch = 0;
private void txtSearch_TextChanged(object sender, EventArgs e)
{
int x = 0;
string match = txtSearch.Text;
if (txtSearch.Text.Length != 0)
{
bool found = true;
while (found)
{
if (lbBranches.Items.Count == x)
{
lbBranches.SetSelected(lastMatch, true);
found = false;
}
else
{
lbBranches.SetSelected(x, true);
match = lbBranches.SelectedValue.ToString();
if (match.Contains(txtSearch.Text))
{
lastMatch = x;
found = false;
}
x++;
}
}
}
}
When I compile and start typing into the search box, I get this error:
Object reference not set to an instance of an object.
The line in question is:
match = lbBranches.SelectedValue.ToString();
I have no idea what could be wrong there, anyone got an idea?
Thanks!
SelectedValue of the listbox will only return a value if you have specified the ValueMember property of the listbox to indicate a property from which you would like to read the value for the selected item. The property you want to use in this case is SelectedItem:
match = lbBranches.SelectedItem.ToString();
when the user is entering text it's possible that no value has been selected (hence the error) -- keep in mind that what is being entered by the user has no mandatory or direct association with selections in the controls listbox sub-element
it's possible what you're doing might be simpler to implement with a full combo-box control and I think some of the examples at MSDN could be very helpful for you as well
Ok, what I have going on is a textbox that has been filled with some text depending on what was selected from a listbox.
say the textbox looks like this:
blah blah ??? as?f
what I need to figure out how to do is whenever the user clicks in the textbox and deletes a "?" character, I would like to replace that character with an * and then whenever they try to delete the * it will be replaced by a "?" , so that the end result will look something like
blah blah **? as*f
if they deleted all but one "?".
No matter how long I have searched online I cannot seem to find anything similar.. the closest thing I have found is this question - Determine when and which character is added or deleted in a Text Box
But that doesnt really help for what I am trying to do.. if anyone has a good idea on where to start looking or even how to do it I would be very greatfull!
thanks in advance!
EDIT: Yes, this is for a Windows Form application, sorry i forgot to specify that. O.o
You can handle KeyDown event and bypass default handling. The event handler can look like the following:
public void OnKeyDown(Object sender, KeyEventArgs e)
{
char[] text = textBox.Text.ToCharArray();
int pos = textBox.SelectionStart;
switch (e.KeyCode)
{
case Keys.Back: if (pos == 0) return; pos --; break;
case Keys.Delete: if (pos == text.Length) return; break;
default: return;
}
switch (text[pos])
{
case '?': text[pos] = '*'; break;
case '*': text[pos] = '?'; break;
default: return;
}
textBox.Text = new String(text);
e.Handled = true;
}
You may also want to add checks for modifier keys, adjust cursor position, and implement custom behavior when text is selected, if needed.
Store textbox.Text in some string, after each key press (textbox.KeyPress) by comparing saved string with text inside textbox, find out if '?' was deleted, if it was insert '*' into textbox text on the right place.
//get indexes of all '?'
list<int> charlist = new list<int>();
string buff = textbox.Text;
for(int c = 0; c< buff.length, c++)
{
if (buff[c] == '?')
{
charlist.add(c)
}
}
//inside keypress event
foreach(int c in charlist)
{
if (textbox.Text[c] != '?')
{
textbox.Text = textbox.Text.Insert(c, "*");
}
}
I am using two forms, where one is a rich text editor with menus and a rich text box and the second form is for search and replace and contains four button and two text boxes. I have managed to do the find button but I am having problems with Find Next. I am using C# Windows Forms.
Here is the code I am using for Find:
private void button1_Click(object sender, EventArgs e)
{
RichTextBox frm1TB = ((Form1)this.Owner).txtDisplay;
int foundAt = frm1TB.Text.IndexOf(searchText.Text);
if (foundAt == -1)
{
MessageBox.Show("Not Found");
}
else
{
frm1TB.SelectionStart = foundAt;
frm1TB.SelectionLength = searchText.TextLength;
frm1TB.Focus();
}
}
Find next would be something like the following:
if (frm1TB.Text.Length >= frm1TB.Text.SelectionStart + frm1TB.Text.SelectionLength)
{
int foundAt = frm1TB.Text.IndexOf(
searchText.Text,
frm1TB.Text.SelectionStart + frm1TB.Text.SelectionLength);
}
You need to remember index at which you found your previous entry (or even better, at which you should start find next search) and then simply use IndexOf(string, int) overload, which allows you to start search at specified position. First, simply add next search start index field to your class:
private int nextSearchStartIndex;
Now, your Find method needs to keep update this index appropriately:
if (foundAt == -1)
{
this.nextSearchStartIndex = 0;
MessageBox.Show("Not Found");
}
else
{
this.nextSearchStartIndex = foundAt + searchText.TextLength;
// ...
}
And FindNext becomes trivial:
// ...
var foundAt = frm1TB.Text.IndexOf(searchText.Text,
this.nextSearchStartIndex);
// Here you can use exactly same update index logic as in Find
You can't use the IndexOf() method for it, you have to switch to Regular Expressions.
Here is an example how you can easily get all the search entries in RichtBox.Text:
using System.Text.RegularExpressions;
Regex re = new System.Text.RegularExpressions.Regex(searchText.Text.ToString(),RegexOptions.None);
MatchCollection mc = re.Matches(frm1TB.Text.ToString());
foreach (var ma in mc)
{
//do what you want
}