Limiting the maximum text length of ListViewItem? - c#

I have a ListView in a C# based win-form project. Is it possible to limit the maximum length of the title of all ListViewItem inside the ListView ?
UPDATE
I mean the input length , I set the item to editable , so users can rename the items
UPDATE2
Right , It's called "the text" of that item , not the title.

You can utilise the label after edit event of a listview. Here is a sample.
private void listview1_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
try
{
const int maxPermittedLength = 1;
if (e.Label.Length > maxPermittedLength)
{
//trim text
listview1.Items[e.Item].SubItems[0].Text = listview1.Items[e.Item].SubItems[0].Text.Substring(0, maxPermittedLength); //or something similar
//or
//show a warning message
//or
e.CancelEdit = true; //cancel the edit
}
}
catch (Exception ex)
{
}
}
Remember, its tricky, not straightforward, you will have to take care of a few exceptions, but thats homework.. The above code is not a working code, but you have the idea now how to go about it. Read the documentation well, it has a nice example and a warning associated with this event.

What do you mean ListViewItem's title ? is it the item text you mean ? I believe whatever retrievable is fixable and controllable. If it is the item text, you can write a check method
public string SimplifyTxt(string input)
{
if(input.Length>LIMIT_NUMBER)
{
//please shorten the string before display
}
return retStr;
}
and it then can be assigned as
listview1.items.add(new Listviewitem{Text=retVal});

Related

Change Textbox text from another frame(container)

I see here lot of similar question, but I still not find answer that help me in situation.
I have two frame(lets say FrameChild), one is "in" another(practically FrameChild is in this frame, lets say FrameMain).
When I insert all parameters in FrameChild and tap on button witch is on bottom of FrameMain I call method that return string...
Now when i get string i need to change textbox text in FrameChild
I have tray many way.
First idea was something like:
FrameChild frm = new FrameChild;
frm.textbox.text = "somestring";
But nothing happen.
Than i thing use some property.
in FrameChield:
public string setTicNo
{
set
{
textBox.Text = value;
}
}
in FrameMain:
FrameChild frm = new FrameChild;
frm.setTicNo = "somestring";
When i debbuging I get value, but textbox still is empty...
On the end I try to bind textbox text on setTicNo;
public string setTicNo
{
get
{
return setTicNo;
}
set
{
setTicNo = value;
}
}
Xaml:
Text = {Binding setTicNo, Mode=TwoWay,UpdateSourceTrigger=Explicit}
(here i try use more bindings, but every time i get infinite loop.
Please help , I not have more ideas..
Thanx
Did you try building a single view model and bind it to both frames, if it was passed by ref which is the default it will change the value once you do.
A side note implement a INOTIFYPROPERTYCGANGED in the View model

WinForms (C#) input field with database-driven autocomplete

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?

Win 8.1 SearchBox SuggestionsRequested

I got an userControl that contains a searchBox.
This UserControl is inside another one.
I got a strange behavior while i'm searching, because the suggestionCollection works in a strange way.
Example :
in the searchBox i write something all works perfectly, if i choose the item it also works.
But if i try to use backspace (after the choose) i got no suggestion.
I cannot understand why it doesn't work.
That's the code
//var deferral = args.Request.GetDeferral(); //it seems to not influence the behavior
var suggestionCollection = args.Request.SearchSuggestionCollection;
try
{
TransporterExt tr_search = new TransporterExt();
//queryText is a string inserted in the searchBox
if (string.IsNullOrEmpty(queryText)) return;
tr_search.name = queryText;
suggested.Clear(); //that's a collection..
//just a search that return a collection of objects TransporterExt
querySuggestions = await TransporterService.Search_StartsWith(tr_search);
if (querySuggestions.Count > 0)
{
int i = 0;
foreach (TransporterExt tr in querySuggestions)
{
string name = tr.name;
string detail = tr.trId.ToString();
string tag = i.ToString();
string imageAlternate = "imgDesc";
suggestionCollection.AppendResultSuggestion(name, detail, tag, imgRef, imageAlternate);
this.suggested.Add(tr);
i++;
}
}
}
catch (System.ArgumentException exc)
{
//Ignore any exceptions that occur trying to find search suggestions.
Debug.WriteLine(exc.Message);
Debug.WriteLine(exc.StackTrace);
}
//deferralComplete(); //it seems to not influence the behavior
The problem is that: all the variables have the right value, but the suggestion panel appears only if i make a particular search: it appears when i change the first letter of search, or after an wrong seach
What appends when i make a search
What appends if i use the backspace, and i what i want to fix
As i said, all works perfectly, after the "backspace" action the suggestionCollection got the right value...but the panel is missing.
Could someone help me?
You can use SearchBox and SuggestionRequested event to fire the event when type on the SearchBox. I will show an Example
<SearchBox x:Name="SearchBoxSuggestions" SuggestionsRequested="SearchBoxEventsSuggestionsRequested"/>
and write the SearchBoxEventsSuggestionsRequested handler in the code behind
private void SearchBoxEventsSuggestionsRequested(object sender, SearchBoxSuggestionsRequestedEventArgs e)
{
string queryText = e.QueryText;
if (!string.IsNullOrEmpty(queryText))
{
Windows.ApplicationModel.Search.SearchSuggestionCollection suggestionCollection = e.Request.SearchSuggestionCollection;
foreach (string suggestion in SuggestionList)
{
if (suggestion.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase))
{
suggestionCollection.AppendQuerySuggestion(suggestion);
}
}
}
}
You can add the keyword to SuggestioList, and it will show in the dropdown when you type on the Searchbox.
Create the SuggestionList
public List<string> SuggestionList { get; set; }
initialize the list
SuggestionList = new List<string>();
and add keywords to the list
SuggestionList.Add("suggestion1");
SuggestionList.Add("suggestion2");
SuggestionList.Add("suggestion3");
SuggestionList.Add("suggestion4");
SuggestionList.Add("Fruits");
Thanks.

Searching ListBox control and programmatically selecting closest match

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

Why is text in TextBox highlighted (selected) when form is displayed?

I have a form containing a TextBox in C# which I set to a string as follows:
textBox.Text = str;
When the form is displayed, why does the text in the texbox appear highlighted/selected?
The text box has a TabIndex of 0 and TabStop set to true. This means that the control will be given focus when the form is displayed.
You can either give another control the 0 TabIndex (if there is one) and give the text box a different tab index (>0), or set TabStop to false for the text box to stop this from happening.
The default behavior of a TextBox in Windows Forms is to highlight all of the text if it gets focused for the first time by tabbing into it, but not if it is clicked into. We can see this in Reflector by looking at the TextBox's OnGotFocus() override:
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
if (!this.selectionSet)
{
this.selectionSet = true;
if ((this.SelectionLength == 0) && (Control.MouseButtons == MouseButtons.None))
{
base.SelectAll();
}
}
}
It's that if statement that is causing the behavior that we don't like. Furthermore, to add insult to injury, the Text property's setter blindly resets that selectionSet variable whenever the text is re-assigned:
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
this.selectionSet = false;
}
}
So if you have a TextBox and tab into it, all the text will be selected. If you click into it, the highlight is removed, and if you re-tab into it, your caret position (and selection length of zero) is preserved. But if we programmatically set new Text, and tab into the TextBox again, then all of the text will be selected again.
If you are like me and find this behavior annoying and inconsistent, then there are two ways around this problem.
The first, and probably the easiest, is to simply trigger the setting of selectionSet by calling DeselectAll() on form Load() and whenever the Text changes:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.textBox2.SelectionStart = this.textBox2.Text.Length;
this.textBox2.DeselectAll();
}
(DeselectAll() just sets SelectionLength to zero. It's actually SelectionStart that flips the TextBox's selectionSet variable. In the above case, the call to DeselectAll() is not necessary since we are setting the start to the end of the text. But if we set it to any other position, like the start of the text, then calling it is a good idea.)
The more permanent way is to create our own TextBox with the desired behavior through inheritance:
public class NonSelectingTextBox : TextBox
{
// Base class has a selectionSet property, but its private.
// We need to shadow with our own variable. If true, this means
// "don't mess with the selection, the user did it."
private bool selectionSet;
protected override void OnGotFocus(EventArgs e)
{
bool needToDeselect = false;
// We don't want to avoid calling the base implementation
// completely. We mirror the logic that we are trying to avoid;
// if the base implementation will select all of the text, we
// set a boolean.
if (!this.selectionSet)
{
this.selectionSet = true;
if ((this.SelectionLength == 0) &&
(Control.MouseButtons == MouseButtons.None))
{
needToDeselect = true;
}
}
// Call the base implementation
base.OnGotFocus(e);
// Did we notice that the text was selected automatically? Let's
// de-select it and put the caret at the end.
if (needToDeselect)
{
this.SelectionStart = this.Text.Length;
this.DeselectAll();
}
}
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
// Update our copy of the variable since the
// base implementation will have flipped its back.
this.selectionSet = false;
}
}
}
You maybe tempted to just not call base.OnGotFocus(), but then we would lose useful functionality in the base Control class. And you might be tempted to not mess with the selectionSet nonsense at all and simply deselect the text every time in OnGotFocus(), but then we would lose the user's highlight if they tabbed out of the field and back.
Ugly? You betcha. But it is what it is.
The answers to this question helped me a lot with a similar problem, but the simple answer is only hinted at with a lot of other complex suggestions. Just set SelectionStart to 0 after setting your Text. Problem solved!
Example:
yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
You can also choose the tab order for your form's controls by opening:
View->Tab Order
Note that this option is only available in "View" if you have the Form design view open.
Selecting "Tab Order" opens a view of the Form which allows you to choose the desired tab order by clicking on the controls.
To unhighlight a text field, with VS 2013, try init with:
myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);
And add the method:
public void myTextBox_GotFocus(object sender, EventArgs e)
{
myTextBox.SelectionLength=0;
}
I haven't tested this on C# but I ran into the same issue using a C++ WIN32 dialog box. Is seems like you can change the behavior by returning FALSE from OnInitDialog() or WM_INITDIALOG. Hope this helps.
Here is what worked for me
public void SetNotes(string notes)
{
notesTextBox.Text = notes;
notesTextBox.Select();
notesTextBox.SelectionLength = 0;
notesTextBox.SelectionStart = notes.Length;//place cursor at end of text
}

Categories