Problem with ComboBox autocomplete when adding values dynamically - c#

In WinForms application, I have a combobox which I am trying to populate with values based on user input. For example if the user types m it should show him all the values that starts with the letter m, but I dont want to add all the values in the beginning because there are a lot of values.
To achieve this, I created an event textchanged and when a user inputs for example the letter m my program goes to my database and adds all the values with the letter m to the combobox.
The problem that I think that the combobox first sees if it should autocomplete (suggest) values and only after that it adds the values.
How can I make it add the values first or make the combobox check again if it should suggest values?
Here is my code:
private void comboBox1_TextChanged(object sender, EventArgs e)
{
comboBox1.Items.Clear();
for (int i = 0; i < MilkProducts.Length; i++)
{
if (MilkProducts[i].StartsWith(comboBox1.Text))
{
comboBox1.Items.Add(MilkProducts[i]);
}
}
}

It seems you may have to use Win32 API (using PInvoke) here by sending appropriate message to the Combo box to show the search result "after" the event handling is done
Please refer to the below URL and you may find the what you are looking for:
http://msdn.microsoft.com/en-us/library/bb775792(VS.85).aspx

i think problem is you are clearing all the items in ComboBox at comboBox1.Items.Clear() and then accessing its contents at comboBox1.Text may be you should try doing it differently. or clear it at the end.

Related

How to disable combox dropdown when user enters text into the combox

I have a simple combobox in c# forms which is populated from an array.
I have set AutoCompleteMode to SuggestAppend and AutoCompleteSource to ListItems. This allows me to filter through the list quickly by typing a string into the combobox and matching items are displayed as I type along. This works great.
However, when the drop down list is open and I start typing, the filtered list appears on top of the dropdown list but I cannot select from the filtered list but only from the drop down.
How to disable drop down list while open as soon as user enters a character into the combobox.
Currently only have one method for the combobox
private void SelectJobDropdown_SelectedIndexChanged(object sender, EventArgs e)
{
//plenty of code here
}
I have tried adding other methods for the combobox such as KeyPress or Keydown but none seems to be working for as I'm very likely doing something wrong
Using Visual Studio 2015
If I understood you correctly you don't like the overlapping list over the old drop down. Since you type letters into the ComboBox I would suggest to use the comboBox1_TextUpdate event. This nice line of code should fix your problem:
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
comboBox1.DropDownStyle = ComboBoxStyle.Simple;
Setting the ComboBox.DropDownStyle property, which
specifies whether the list is always displayed or whether the list is displayed in a drop-down[...]
to ComboBoxStyle.Simple, which
Specifies that the list is always visible and that the text portion is editable. This means that the user can enter a new value and is not limited to selecting an existing value in the list.
will remove the original dropdown (long list) and only the filtered results remain.

WinForms: providing text editor with dynamic suggestions popup

I want to implement something like Google's search bar behavior for our application: user must be able to enter user name as free text and based on entered data system must provide a couple of suggestions on a popup bar based on already existent user names.
Here's the brief algorithm:
user enters some character to text edit box
system fires some changing event with web service call inside it that updates suggestions list data
Text edit must also provide an ability to enter and keep a free text to create new user, not just looking up for existent
I can't use devexpress's lookupeditds - they allow to keep only values, presented in datasource - even if new value has being processed inside ProcessNewValue by adding to datasource,
Changing event fires one more time with refreshing my datasource overwriting new unique value.
Now I am looking forward Combobox control. But looks like there is no ability to enter free text alongside with displaying suggestions popup.
I can't use devexpress's lookup edits - they allow to keep only values, presented in datasource - even if new value has being processed inside ProcessNewValue by adding to datasource,
I believe you're wrong here because you can use the DevExpress LookUpEdit with easy:
class AutoCompleteLookUpEdit : LookUpEdit {
List<string> suggestions = new List<string>();
public AutoCompleteLookUpEdit() {
Properties.DataSource = suggestions;
Properties.ImmediatePopup = true;
}
protected override void ProcessFindItem(KeyPressHelper helper, char pressedKey) {
suggestions.Clear();
// add search suggestions here depending on helper.Text value
suggestions.Add("google");
suggestions.Add("devexpress");
// ...
base.ProcessFindItem(helper, pressedKey);
}
}
Take a look at the How to create an editor with a dynamic autocomplete list for the detailed example.
P.S. You can use the AcceptEditorTextAsNewValue property to control whether or not lookup accepts entered text as valid value even it does not belong the underlying data source.

Add text box with corresponding combo box dynamically

I am creating a windows form app with the following goal:
get a list of products, each with a unique name and a category (from an enumerated list) from a user (and then do some things after, but this is not relevant to the question).
The idea is I would like to have the user specify they would like to configure "n" products by entering a value in a text box. I have the event handler for the text box calling a method which sets a variable to this value n. This value, "n", will be used as the loop counter, or what have you - the point is it will create the bound for the number of boxes to create.
I would then like to add (dynamically based on n), n number of (text box / combo box) pairs to the form. If there is no room to add another (text box / combo box) pair below the last one created, it should create another column.
n is unbounded, but, realistically, will likely never exceed 20. In any event, I'd like to be able to handle it if there are more products than this.
the options in the combo box will be filled from a string list that is passed in at run time, but will be consistent per box, per instance of this Form application.
i tried to enter a mock up image but stack overflow won't let me until i have earned some reputation points :(
I understand how to create a number of boxes using something like the code below, but its the finer points i'm stuck on. Can anyone help?
thanks!
` private void Method1()
{
int boxes = Int32.Parse(NumProducts.Text);
for (int i = 0; i < boxes; i++)
{
TextBox tb = new TextBox();
tb.Location = new System.Drawing.Point(40, i * 20);
tb.Name = "TextBoxName" + i.ToString();
tb.Size = new System.Drawing.Size(184, 20);
tb.TabIndex = i + 2;
tb.Text = String.Empty;
panel1.Controls.Add(tb);
}
}
private void NumProducts_TextChanged(object sender, EventArgs e)
{
Method1();
}`
Sounds to me like a DataGridView would be the better choice here. You can configure it with a DataGridViewTextBoxColumn as the first column and a DataGridViewComboBoxColumn for the second. It supports a "new row" as the last item.
Read the docs. Drop one on a form and play with it.
Asking the user for the number of rows in advance is not very good from a usability viewpoint.
You should rather create an interface that keeps creating new boxes as the user inputs things, either by having a "new row" row that activates when the user types something into it (the empty row isn't saved) or by having a "new row" button.
To achieve the layout, use a FlowLayoutPanel control, and add the controls to this instead of to the panel as you are already doing. That should transparently take care of the columns issue, and add scroll bars if the user goes beyond your anticipated maximum number of edit boxes. General info on the FlowLayoutPanel here (as well as many others).

How to change the cell appearence of the filter in UltraWinGrid

I am using UltraWinGrid control and I want to customize its filtering.
I am able to get all the values from the ValueList property .
private void dgridData_BeforeRowFilterDropDown(object sender, BeforeRowFilterDropDownEventArgs e)
{
// Get each item from the list
foreach (ValueListItem item in e.ValueList.ValueListItems)
{
// Do Something
}
}
I want to show the values in the dropdown ( see picture ) as follows :-
(All)
(Custom)
(Blanks)
(NonBlanks)
*********
*********
*********
The values after (NonBlanks) should appear as asterisks .
One of the option I can think is to attach a masked editor to the current editor , to change the display. But I dont know how to attach an editor control in this scenario.
Sharing some links on I was going through :-
Filtering Rows in Ultragrid
Removing default entries from Infragistics UltraWinGrid RowFilterDropDown
You are welcom to let me know of other options to acheive the same.
I'm not in front of my pc with Infragistics on it right now. But Couldn't you just loop through the items and change the DisplayText?
private void dgridData_BeforeRowFilterDropDown(object sender, BeforeRowFilterDropDownEventArgs e)
{
// Get each item from the list
foreach (ValueListItem item in e.ValueList.ValueListItems)
{
if (!item.DisplayText.StartsWith("("))
item.DisplayText = new String('*', item.DisplayText.Length);
}
}
I'm just typing the code from the top of my head, pardon any errors.
What should the filtering do after you have changed the list to be strings of asterisk characters? Are you looking to provide a filter based on the length of the items?

Controlling C# DataGridView with an Arraylist in VS2008

I'm having some problems with a datagridview element I'm using in VS2008.
This DataGridView is actually a tab in a TabControl element.
I gave it 5 colums which need to be filled up with elements from a costum Object i made.
It's basically a small library application which contains a main class and several classed derived from it. They all have a ToString() method which represents the data as a string of keywords containing the values needed for me to fill up the datagridview.
I only need the first 5 though, some objects will have up to 12 keywords.
Currently, Whenever I add an object, the datagrid doesn't fill itself, instead it adds an amount of columns equall to the amount of keywords the specific object has.
What i'm currently doing is this:
public void libDataGrid_Click(object sender, EventArgs e)
{
if(this.manager.Lib.LibList[0] != null)
{
libDataGrid.DataSource = this.manager.Lib.LibList;
libDataGrid.Refresh();
}
}
this.manager.Lib.LibList returns and ArrayList, in which all objects are stored. The ArrayList can contain elements of all derived classes, but since they are all connected, the string representation will always contain the elements I need to fill up the grid.
I don't see how I can filter only the first five and them have them put in the correct colums.
And another thing. Currently I can only refresh the DataGridView by clicking it. It should change on when I switch to it switch to its specific tab on the Tabcontrol I mean.
I tried adding an argument for SelectedIndexChanged, but that does nothing really...
Or at least, it doesn't appear to do anything.
What I mean is I commented out the code above and added this instead:
public void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
libDataGrid.DataSource = this.manager.Lib.LibList;
libDataGrid.Refresh();
}
This refreshes it everytime the tab is changed, no matter to which one.
I had to remove the if-statement, since it gave me an Exception. Probably because the length of the ArrayList isn't set on initialisation.
I'm a little confused by the question, but here are some thoughts:
DataGridView has an AutoGenerateColumns property; if you don't want it to create its own columns, set this to false
To bind to existing columns, the DataPropertyName must be set on each
DataGridView (in cmomon with any list control using TypeDescriptor) will hugely prefer List<T> (for some T != object) to ArrayList, since it can get meta-data even for an empty list. In general, in 2.0 using ArrayList is a mistake.
I can only give a partial answer but I think the reason that
public void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
libDataGrid.DataSource = this.manager.Lib.LibList;
libDataGrid.Refresh();
}
isn't working, is because you need to add this line where tabControl1 is being initialized. I've had this problem where VS won't do this itself.
tabControl1.SelectedIndexChanged += new EventHandler(tabControl1_SelectedIndexChanged);
If I am understanding your problem, it seems similar to a problem that I was struggling with recently in this thread on DataGridViews in C#/.NET2.0
Try calling:
libDataGrid.Invalidate();
This should force Windows to redraw your control. No need to reattach the datasource and refresh. (I think you can safely comment out those 2 lines.)
Also: What was the Exception that you were getting?
And did you use the "Data Source Configuration Wizard" to help you with the dataGridView?

Categories