Autocomplete TextBox for C# Winform VS2008 clarification needed - c#

I am working on C# winform vs2008 project. Requirement is to show line level details into grid and grid one text box cloumn user will type the text and it should populate the autocomplete text. Autocomplete search should based on one column only, but need to show additional one column to user. Exampe : Name and Phone number. user will search based on Name only additional column phone should display purpose.
I have following query :
1) Database is large, is there any free autocomplete 3 party tool available.?
2) How can i show muliple columns in autocomplete.
Please let me know, how i can show multiple columns in autocomplete.
I am stuck here.. please help me out..
Thanks and Regards
Ram

There are third party components that can be used to support multiple column drop down, for example DevExpress's LookUpEdit, Infragistics's UltraCombo and Telerik's RadMultiColumnComboBox. You can change the filter then popup the dropdown when typing, but that is not going to beat the performance of Windows's autocomplete, which uses a second thread to enumerate candidates.
If you have that much data, auto-sizing the drop down columns and animation probably need to be disabled if your control library enables them by default.

public Class YourClass
{
public string Name;
{
get;
private set;
}
public string PhoneNo;
{
get;
private set;
}
public override string ToString()
{
return String.Format("{0,-50} {1,-15}", this.Name, this.PhoneNumber);
}
}
internal class YourForm : Form
{
ComboBox YourComboBox = new Combobox();
//Set the style of your combobox such that it looks like a text box
BindingList<KeyValuePair<string, YourClass> bl = new Binding<string, YourClass>();
//Query for the data to populate the BindingList
//Lets say you put the UserId or ContactId of the person in the Key..
YourComboBox.DataSource = bl;
YourComboBox.DisplayMember = "Value";
YourComboBox.ValueMember = "Key";
}
Do what ever you are doing for autocomplete
There's no ready and elegant implementation for what you need. What I gave you would display the results like in a table..
Eg:-
Reese W 32
Pamela A 40
but with the name, taking about characters of space in what ever font the control renders..
(You will have to look at this answer in edit mode to see it)
If you want exactly what you need, you WILL have to use some available 3rd party controls or write one of your own. And as some one said, it's too much of code..

Related

Use DataBinding to maintain the alphabetic short between listBoxes

I've been programming some little project in Visual Studio using c# (.NET FRAMEWORK) and in some of my windows forms I want to show in different lisboxes the information about some object.
In my program I got a class named Client that has some Properties: an int called DNI (this is the one that identifies a Client), a string called Name and an int called Telephone. I want a form to show 3 different listboxes, each one with the list of elements of a collection of Client objects. The point is that a Client object has it's Properties showed in the same index of each listBox (to be said, reading horizontally you see the three values of the properties). I have implemented a button in top of each one that alphabetically sorts the elements of the listBox, but I would like to make a Binding between them so When you alphabetically sort one listbox, the other two sort their elements to match the new order of elements in the one alphabetically sorted.
I've been told the class DataBindingscan be used to do this. I've tried searching on the internet about it but achieved nothing and reading the documentation didn't help either, so I ended up posting it here. How can I use DataBindings to solve this? Any help or hint will be appreciated, thanks in advance.
What must I write to bind the indexes of them?
I recommended a datagridview; you seem to have tabular data that you want to show in a tabular fashion.. However, we'll demo all of it.
Easiest route:
Make a new winforms project
Add a DataSet type of file, open it, right click the design surface and choose Add .. DataTable
Name the table Client
Right click it and add column, call it DNI, use the props grid to make its type Int32
Add a string column Name
Add an int column Telephone
Save, switch to Form1 designer
Open Data Sources window (View menu, Other Windows)
Drag the Client node onto the form. A datagridview appears along with some stuff in the tray. Remove the navigator; it's not so useful in this context
Add 3 listboxes to the form
For each listbox:
Use the props grid to set its DataSource to the bindingsource
Set the DisplayMember to a different column - one DNI, the other Name and the third Telephone
That's it for now, run the app. Type some data in the datagridview. Note that when you sort by clicking the DGV header, the listboxes follow; this is because the sort instruction is being carried out by the bindingsource, and all controls bind through the bindingsource:
So that's thngs bound through a bindingsource to a strongly typed datatable, which is conceptually not really any different to what you have. The bit of work making the table and its columns in the design surface is the notional equivalent of making a class with properties. Indeed if you were to open the DataSetBlahBlah.Designer.cs file you'd find a class ClientRow with 3 properties DNI, Name, Telephone
You could change up everything you've made to be based on e.g. a List<Client> but your sorting life becomes slightly more awkward because a BindingSource doesn't understand how to sort it. As such you'd end up with something like:
//class property
private List<Client> Clients = new();
//in constructor
clientBindingSource.DataSource = Clients;
//in button that does sorting:
clientBindingSource.DataSource = Clients.OrderBy(c => c.name); //etc
Personally I'd leave it as a strongly typed datatable; for what you'd want out of a List<Client> a ClientDataTable collection of ClientRow are surface similar enough..
Clients.Where(c => c.Name == "John"); //how you might search a List<client>
ClientsDT.Where(c => c.Name == "John"); //how you might search a ClientDataTable
Clients.Add(new Client(){ DNI = 1, Name = "a", Telephone = 1 } ); //add to a List<Client>
ClientsDT.AddClientsRow(1, "a", 1); //how you might add to a ClientDataTable
etc
If you have already implemented a button for each, you've almost finished.
Every ListBox have to be bound with a List of Client, showing a specific property as DisplayMember.
The button of each ListBox can sort the List and refresh all of the ListBoxes.
If you want more information, please post some of your code.

WPF Datagrid UserControl with definable columns

I have an object something like this:
public class Item
{
public string Name;
public int Id;
public int Quantity;
public decimal Volume;
public decimal Cost;
}
I'm wanting to create a reusable user control which would take a list of these objects and display them in a datagrid. The trick is that I want to specify which of the properties are shown in the datagrid for each instance of the control. Unfortunately my WPF skills are not up to the tasks and I don't want to create a specific control for each combination that I will want to use, as that feels like a lot of work for very similar code items. Any help to pointers of how to accomplish this would be greatly appreciated.
You can use the Columns property of your datagrid to interact with the columns and hide the columns you don't want.
datagrid.Columns.RemoveAt(IndexOftheColumn);
or if you named your columns
datagrid.Columns.RemoveAll(x => x.Name = "column name");
or if it is possible that you will need to column later
datagrid.Columns[IndexOftheColumn].Visibility = Visibility.Collapsed;
It is also possible to do this with pure Xaml with bindings but since you are new to Wpf I would suggest doing it in the code behind (the .cs of your Wpf control) first.
As for selecting which columns to hide you can pass a list of names for the columns you want to remove in the constructor of the control or with a binding. There are a lot of ways to do it.
Or you could do the opposite and add columns dynamically based on your needs.
Note that this question has been asked before

Bind a datagridviewcolumn to a nested class

In my C# program I have a windows form (Winforms) containing a datagridview. The last column of this datagridview is a datagridviewcomboboxcolumn, and each comboboxcell (in each row) has its own datasource.
As there can be a lot of rows, I want to make a binding to populate the datagridview quickly. I already tried to bind the first columns then populate the datasources of the comboboxes afterwards (in the RowsAdded event), but it takes too much time.
My class Data is as follows :
public class Data
{
public string _aaa { get; private set; }
public string _bbb { get; private set; }
public string _ccc { get; private set; }
public List<Room> _rooms_list { get; private set; }
...
}
And the Room class contains the following members :
public ElementId Id { get; }
public virtual string Name { get; set; }
When the datasource of the datagridview is bound to a list of Data objects, I want the corresponding comboboxcell to be filled with the corresponding list of Room objects, with Name as DisplayMember and Id as ValueMember.
I searched on the web but didn't find the answer if it's possible or not.
Thanks a lot for your help.
Edit
More info : I want to let the user select the desired Room among a list of detected/found Rooms, so that's why I chose comboboxes. The results of my calculation already are shown as strings in two of the (bound) string columns.
I also want to make the whole thing sortable, so I use a SortableBindingList to bind the DGV with the list of Data objects : mainDataGridView.DataSource = new SortableBindingList<Data>(_data);
If you have many rooms in your list, it will be slow to create a new combo-box for each cell as you're already experiencing. I recommend creating one combo-box in code and then adding it to each cell.
Edit: If you're only using the grid for display, you can enhance the performance by simply displaying the rooms as text instead of combo-boxes. You can then denote the selected room by changing the font style (e.g. bold) or color, or by adding some symbol (e.g. asterisk) or word (e.g. [selected]). Separate each room with a new line. Here is an example function, but I don't know how your rooms are selected, so let's assume that you have a bool Selected { get; set; } in your Room class:
string ListRooms(List<Room> rooms){
string result = "";
foreach(Room r in rooms){
result += r.Selected ? "* " : "";
result += r.Name + "\r\n";
}
return result;
}
Now in the OnRowsAdded event, you can call this function and display the result in a simple text cell.
Edit 2: If you're allowing the users to select a room from the list of available rooms, and this list is different from one row to another, then combo-boxes are what we usually use for that purpose. However, if you have many rows then it takes longer to load like you're experiencing.
In that case, you're best bet is to not load the combo-boxes at the beginning. Leave them empty and when the user clicks on a combo-box to select a room, use Ajax to fetch the list of rooms for that row from the server and populate the combo-box using JavaScript. This solution will perform well, but the page may become a little heavy if the user has to select a room for all rows. I believe that all modern browsers will still be capable of handling it smoothly, but it might become and issue if your users use your web application on a mobile device.
Alternatively, you can use popups instead of combo-boxes. Replace the combo-boxes with buttons or links. They can read something like "Select a Room". When the user clicks on the button/link, use Ajax to load a popup with a list of available rooms for that row. The user selects a room from the list and clicks the button to close the popup then you display the select room using JavaScript either on the button/link that's used to open the popup, or in a separate column for the selected rooms which can be initially blank. This solution is easier to implement (you can use jQuery or Bootstrap), more flexible (you can display whatever you want on the popup), and performs perfectly regardless of the number of rows.

DataGridView TextBox column with Autocomplete that populates other cells

I have a simple DataGridView:
I have a class:
public class TemplateItem
{
public string Name { get; set; }
public decimal Price { get; set; }
}
And a list to store templates:
List<TemplateItem> templates = new List<TemplateItem>();
// Some code to populate the list
For the "Name" cell in the grid, I want to:
display autocomplete options from the templates list when the user types in the cell
automatically set the "Price" cell to the price of the autocomplete option that the user has selected (the user can change the price afterwards)
allow the user to type in something not available in the templates list
I know how to enable autocomplete by using EditingControlShowing event, like in this question.
I don't know how to detect the selection of an autocomplete option. Using KeyDown event doesn't work for me - it never fires.
And I don't know how to get the price of the selected option. Supposing I was able to catch the "option selected" event, I could go through the templates and find the one with the same name... but that seems ugly code to me. I should be able to pass the information about the price for each option somehow, right?
I ended up re-modifying my user interface, so that the grid no longer allows the user to enter new rows. Instead, I have a separate ComboBox (DropDownStyle set to DropDown) with autosuggest turned on and an "add" button to insert new rows based on the value from the combobox. If an existing template is selected, its price is inserted as well; otherwise, just the entered text is inserted.
If anyone knows of how to achieve the same functionality within the datagridview, please let me know.

Hide a Column from ColumnChooser

Currently I'm developing an application with devexpress, and I had set two columns to hide like this:
gridView1.Columns[2].Visible = false;
However, when I run my program, there is an option from the DataGrid called "Selector de Columnas" (in English ColumnChooser). In this option the two columns that I set to be hidden are shown. I don't want the user to see these columns but I still need them, so I just want to hide them.
I searched in the online documentation from Devexpress and they state here that columns can be hidden with the ShowInColumnChooser property. However I'm not able to hide these columns in the ColumnChooser. They don't show you any example, just this line of code:
public bool ShowInColumnChooser { get; set; }
I guess this is a property from some Devexpress control, however they don't state how to use it.
All the links you referred to are related to the WPF DXGrid, but as far as I can see from your screenshot, you are working with the XtraGrid (WinForms). If so, you should use the OptionsColumn.ShowInCustomizationForm property as follows:
column1.OptionsColumn.ShowInCustomizationForm = false;
Related help articles:
Column and Card Field Overview
Customization Form
If you want to prevent a specific column from being showed/hidden, set the column's properties OptionsColumn.ShowInCustomizationForm and OptionsColumn.AllowShowHide to false.

Categories

Resources