textbox auto complete (Multi Line) - c#

I am making a auto suggestion / complete textbox in C#, i followed below link, but text box isnt showing the suggestions
How to create autosuggest textbox in windows forms?
//-------- Get all distinct description -----------------------------
OleDbCommand command = new OleDbCommand(Queries.qry16, Connection);
OleDbDataReader reader = command.ExecuteReader();
//--------- Storing ------------------------------------
while (reader.Read())
{
namesCollection.Add(reader.GetValue(0).ToString());
}
//----------- Close after use ---------------------------------------
reader.Close();
//----------- Set the auto suggestion in description box ------------
descriptionBox.AutoCompleteMode = AutoCompleteMode.Suggest;
descriptionBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
descriptionBox.AutoCompleteCustomSource = namesCollection;
Here is my code , it is in load function of winform. And the nameCollection initializtion is in constructor... kindly please help to make it working.
I am editing my post rather then creating new... I have tried the my own code in single line textbox and it worked. Now i want the same in multi line... For research i googled more then 2 days trying different codes (one with intelli sense) but it didnt worked as auto suggestion available in textbox. Can any one give me suggestion to code the whole procedure to multi line.. Thank you.

AutoCompleteSource does not work on multiline TextBox controls.
Wich means you need to make it from scratch:
I would make a ListBox to display the content of your autocomplete:
var listBox = new ListBox();
Controls.Add(listBox);
You need eventhandling on your textbox however this is a bit crude, so i would rewrite it to stop the keyupevent at some point:
private void textBox_KeyUp(object sender, KeyEventArgs e)
{
var x = textBox.Left;
var y = textBox.Top + textBox.Height;
var width = textBox.Width + 20;
const int height = 40;
listBox.SetBounds(x, y, width, height );
listBox.KeyDown += listBox_SelectedIndexChanged;
List<string> localList = list.Where(z => z.StartsWith(textBox.Text)).ToList();
if(localList.Any() && !string.IsNullOrEmpty(textBox.Text))
{
listBox.DataSource = localList;
listBox.Show();
listBox.Focus();
}
}
Now all you need is a handler to set the text in your textBox:
void listBox_SelectedIndexChanged(object sender, KeyEventArgs e)
{
if(e.KeyValue == (decimal) Keys.Enter)
{
textBox2.Text = ((ListBox)sender).SelectedItem.ToString();
listBox.Hide();
}
}
Put in null checks where appropriate

You need to add a New Component class by 'Adding New Item'. and then write the code for that class and then add that component wherever required..

Try this code as it works in my case:
AutoCompleteStringCollection MyCollection = new AutoCompleteStringCollection();
while (reader.Read())
{
namesCollection.Add(reader.GetString(0));
}
reader.Close();
descriptionBox.AutoCompleteMode = AutoCompleteMode.Suggest;
descriptionBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
descriptionBox.AutoCompleteCustomSource = namesCollection;
con.Close();
Please check if the reader is getting the desired records..:)

Bit of confusion on the "auto-suggestion" since that is basically auto-complete without the permission from the user to "complete" the text. Nevertheless here are a couple of links you might find helpful:
http://docs.jquery.com/UI/Autocomplete
Autocomplete functionality on a textarea
AutoComplete extender for multi-line Textbox
Scroll down on link #2, a user suggested a jquery solution and compare with link #1. You may find a solution.
Third link is from asp forums, similar question like yours was also answered by a link. You might want to check that out.

Thismay help you solving problem ;
You can change table name. you can change the query to load listbox.
ListBox lbox;
private void IletisimBilgileriDoldur()
{
try
{
string strQuery= "Select adres From tblIletisimBilgileri Where adres <> '';";
veri = new OleDbCommand(strQuery,strConn);
veri.CommandType = CommandType.Text;
if (strConn.State == ConnectionState.Closed) strConn.Open();
oku = veri.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(oku);
oku.Close();
txtAdres.AutoCompleteCustomSource.Clear();
if (dt.Rows.Count >= 0)
{
lbox = new ListBox();
for (int count = 0; count < dt.Rows.Count; count++)
{
lbox.Items.Add(dt.Rows[count]["adres"].ToString());
}
}
txtAdres.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
txtAdres.AutoCompleteSource = AutoCompleteSource.CustomSource;
if (strConn.State == ConnectionState.Open) strConn.Close();
}
catch (Exception)
{
if (strConn.State == ConnectionState.Open) strConn.Close();
}
}
private void txtAdres_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
var x = txtAdres.Left;
var y = txtAdres.Top + txtAdres.Height;
var width = txtAdres.Width;
const int height = 120;
lbox.SetBounds(x, y, width, height);
lbox.KeyDown += lbox_SelectedIndexChanged;
lbox.DoubleClick += lbox_DoubleClick;
gbxAdres.Controls.Add(lbox);
lbox.BringToFront();
lbox.Show();
ActiveControl = txtAdres;
}
void lbox_DoubleClick(object sender, EventArgs e)
{
txtAdres.Text = ((ListBox)sender).SelectedItem.ToString();
lbox.Hide();
}

Related

Putting text together inside a listview column out of a mysql database?

I need to be able to change the product inside my database with this program. To do that I need to be able to put them beside each other. How do I do this?
See image.
https://imgur.com/a/0Vy5XaC
I tried to follow a tutorial but I can't really find any...
string connectionURL = #"SERVER=localhost;DATABASE=shopkartje;UID=root;PASSWORD=;SslMode=None";
MySqlConnection connection = null;
MySqlDataReader rdr = null;
try
{
connection = new MySqlConnection(connectionURL);
connection.Open();
string sql = "SELECT * from producten";
MySqlCommand commando = new MySqlCommand(sql, connection);
rdr = commando.ExecuteReader();
while (rdr.Read())
{
lvproducten.Items.Add(rdr.GetString("ID"));
lvproducten.Items.Add(rdr.GetString("Productnaam"));
}
}
catch
{
MessageBox.Show("Kan bestand niet openen ");
}
finally
{
connection.Close();
rdr.Close();
}
So what code is it that puts these next to each other? They need to be clickable for me to be able to change or update it.
In a ListView in Detail mode you have many columns of data (subitems)
To add in a single call the data for the 'row' you need to prepare an array
string[] row = { rdr.GetString("ID"), rdr.GetString("Productnaam")};
var lvItem= new ListViewItem(row);
lvproducten.Items.Add(lvItem);
To get back the data from the current selected 'row' you subscribe to the SelectedIndexChanged event and look at your row
void lvproducten_SelectedIndexChanged(object sender, EventArgs e)
{
if (lvproducten.SelectedItems.Count > 0)
{
string id = listView1.SelectedItems[0].SubItems[0].Text;
string product = listView1.SelectedItems[0].SubItems[1].Text;
.... update your textboxes....
}
}
Declare ListView with Details view and add two columns, then iterate through loop
and add items
lvproducten.View = View.Details;
lvproducten.Columns.Add("ID", 100, HorizontalAlignment.Left);
lvproducten.Columns.Add("Productnaam", 150, HorizontalAlignment.Left);
while (rdr.Read())
{
//lvproducten.Items.Add(rdr.GetString("ID"));
//lvproducten.Items.Add(rdr.GetString("Productnaam"));
string[] str = new string[1];
ListViewItem itm;
str[0] = rdr.GetString("ID");
str[1] = rdr.GetString("Productnaam")
itm = new ListViewItem(str);
lvproducten.Items.Add(itm);
}
your on the right track with items.add but each 'item' is a row so you need to add 'sub items' to that row...
ListViewItem item = new ListViewItem(rdr.GetString("ID"));
item.SubItems.Add(rdr.GetString("Productnaam"));
listView1.Items.Add(item);
so in these 3 steps we have firstly created an item, secondly added our first sub item, then finally added it to our list view.
your listview needs to have its property 'View' set to detail but going by your picture you have already done that :)
if you want to add more columns from you database you can simply add more subitems to your code like this...
ListViewItem item = new ListViewItem(rdr.GetString("ID"));
item.SubItems.Add(rdr.GetString("Productnaam"));
item.SubItems.Add(rdr.GetString("AnotherRow"));
item.SubItems.Add(rdr.GetString("OneMoreForLuck"));
listView1.Items.Add(item);
in addition from your comments you would need to set your list view property 'FullRowSelect' to true then us the SelectedIndexChanged event and something like the following...
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
{
//Set the first textbox
textBox1.Text = listView1.SelectedItems[0].SubItems[0].Text;
//Set the second textbox
textBox2.Text = listView1.SelectedItems[0].SubItems[1].Text;
}
}

How do i add a previous and next button to datagridview

I am using Visual studio 2012 and have made a windows form application, for one of the forms I am using a datagridview which shows the information of a table from the SQL database.
I have made the form load information from the datagridview rows directly into a textbox automatically.
SqlDataAdapter SDA = new SqlDataAdapter("SELECT * FROM Stock", con);
DataTable DATA = new DataTable();
SDA.Fill(DATA);
dataGridView1.DataSource = DATA
txtStock3.Text = dataGridView1.SelectedRows[0].Cells[0].Value.ToString();
Descriptioncombo2.Text = dataGridView1.SelectedRows[0].Cells[1].Value.ToString();
txtprice2.Text = dataGridView1.SelectedRows[0].Cells[2].Value.ToString();
The problem is that I need to add a previous button and a next button so that users can navigate through the datagridview rows and see the information in a textbox from each column of a datagridview row. I have looked at similar questions and have browsed through the internet to look for a solution to my problem but i can't seem to find a way which works with my code. Also could you tell me how to add a line of code which tells the user that there is no more rows to select if they click next through all rows of the database.
One way to provide navigation is by using a BindingNavigator where you can remove unnecessary buttons and for TextBox you can data binding.
Code responsible for loading data. Replace the console.writeline in the catch as you see fit e.g. write to a log file etc.
public class DataOperations
{
public DataTable LoadCustomers()
{
DataTable dtCustomers = new DataTable();
using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.ConnectionString))
{
string commandText = #"SELECT [Identfier], [CompanyName],[ContactName],[ContactTitle] FROM [NORTHWND1.MDF].[dbo].[Customers]";
using (SqlCommand cmd = new SqlCommand(commandText, cn))
{
try
{
cn.Open();
dtCustomers.Load(cmd.ExecuteReader());
dtCustomers.Columns["Identfier"].ColumnMapping = MappingType.Hidden;
dtCustomers.Columns["ContactTitle"].ColumnMapping = MappingType.Hidden;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
return dtCustomers;
}
}
On a form, one BindingNavigator, one dataGridView, one TextBox
DataOperations dataOps = new DataOperations();
BindingSource bsCustomers = new BindingSource();
bsCustomers.DataSource = dataOps.LoadCustomers();
dataGridView1.DataSource = bsCustomers;
bindingNavigator1.BindingSource = bsCustomers;
txtContactTitle.DataBindings.Add("Text", bsCustomers, "ContactTitle");
An alternate to the BindingNavigator is to make the BindingSource form level, private variable. Then in buttons call BindingSource.Move method e.g. bsCustomers.MoveFirst(). Of course there is MoveNext, MoveLast and MovePrevious too.
//first
int i = 0;
this.dataGridView1.CurrentCell = dataGridView1.Rows[0].Cells[dataGridView1.CurrentCell.ColumnIndex];
//prev
int prev = dataGridView1.CurrentRow.Index - 1;
if (prev >= 0)
{
this.dataGridView1.CurrentCell = dataGridView1.Rows[prev].Cells[dataGridView1.CurrentCell.ColumnIndex];
//MessageBox.Show(dataGridView1[0, dataGridView1.CurrentRow.Index].Value.ToString());
}
//next
int next = dataGridView1.CurrentRow.Index + 1;
if (next < dataGridView1.Rows.Count)
{
this.dataGridView1.CurrentCell = dataGridView1.Rows[next].Cells[dataGridView1.CurrentCell.ColumnIndex];
//MessageBox.Show(dataGridView1[0, dataGridView1.CurrentRow.Index].Value.ToString());
}
//last
int i = dataGridView1.Rows.Count - 1;
if (i < dataGridView1.Rows.Count)
{
this.dataGridView1.CurrentCell = dataGridView1.Rows[i].Cells[dataGridView1.CurrentCell.ColumnIndex];
//MessageBox.Show(dataGridView1[0, dataGridView1.CurrentRow.Index].Value.ToString());
}
As an alternate to Karen's solution, if you prefer/must go with buttons to navigate then you'll want to handle the CurrentCellChanged event as well as the following button Click events:
private void DataGridView1_CurrentCellChanged(object sender, EventArgs e)
{
if (this.dataGridView1.CurrentRow != null)
{
txtStock3.Text = dataGridView1.CurrentRow.Cells[0].Value.ToString();
Descriptioncombo2.Text = dataGridView1.CurrentRow.Cells[1].Value.ToString();
txtprice2.Text = dataGridView1.CurrentRow.Cells[2].Value.ToString();
this.prevButton.Enabled = this.dataGridView1.CurrentRow.Index > 0;
this.nextButton.Enabled = this.dataGridView1.CurrentRow.Index < this.dataGridView1.Rows.Count - 1;
}
}
private void PrevButton_Click(object sender, EventArgs e)
{
int prev = this.dataGridView1.CurrentRow.Index - 1;
this.dataGridView1.CurrentCell = this.dataGridView1.Rows[prev].Cells[this.dataGridView1.CurrentCell.ColumnIndex];
}
private void NextButton_Click(object sender, EventArgs e)
{
int next = this.dataGridView1.CurrentRow.Index + 1;
this.dataGridView1.CurrentCell = this.dataGridView1.Rows[next].Cells[this.dataGridView1.CurrentCell.ColumnIndex];
}
The CurrentCellChanged event will handle logic for if you can click Previous or Next. Their respective click events simply move the current cell backwards or forwards one row.
You configure the comulmns in the grid to be your matching types. Then after the query you bind the data to this gridView. You add two buttons where the "next" button will fetch the currentselectedrow of the grid, and set it's follower to be the selected one. previous will do the opposite. This is a small pain in the ass. I hate grids in WinForms. The last 4 years, since I did not see them, have been the happiest years of my lif

How to retain data for dynamically created controls?

I have the following situation:
I have 2 drop down lists (DDL) with auto-postback enabled.
When the user selects something from first DDL, he can choose stuff from 2nd DDL.
When the user selects something from 2nd DDL, I open database (WHERE clause of SQL query is filled with values from DDLs), and dynamically create several text boxes, labels and buttons which I place inside a placeholder.
The problem is: when I click on some of the dynamically created buttons, nothing happens, and I can't retrieve data from dynamically created boxes. Also, placeholder content is lost (all controls).
So my question is: how do I retain data from dynamically created controls on postback?
I have listed a lot of similar articles on this site, and none solves my problem. Another thing is - I can't use view state nor session.
Code is:
public Button btn1 = new Button();
public TextBox txtBoxC1 = new TextBox();
public TextBox txtBoxC2 = new TextBox();
public TextBox txtBoxC3 = new TextBox();
...
...
...
protected void ddl2_SelectedIndexChanged(object sender, EventArgs e)
{
...
...
if some conditions are met:
...
...
String CS4 = ConfigurationManager.ConnectionStrings["connStringName"].ConnectionString;
using (SqlConnection conn4 = new SqlConnection(CS4))
{
SqlCommand cmd4 = new SqlCommand("Select * from table where column1=" +
Convert.ToInt32(ddl2.SelectedValue)+" order by column1", conn4);
conn4.Open();
SqlDataReader rdr = cmd4.ExecuteReader();
while (rdr.Read())
{
txtBoxC1.Text = rdr["column1"].ToString(); txtBoxC1.MaxLength = 3; txtBoxC1.Columns = 3; txtBoxC1.ID = ddl2.SelectedValue + "1";
txtBoxC2.Text = rdr["column2"].ToString(); txtBoxC2.MaxLength = 3; txtBoxC2.Columns = 3; txtBoxC2.ID = ddl2.SelectedValue + "2";
txtBoxC3.Text = rdr["column3"].ToString(); txtBoxC3.MaxLength = 3; txtBoxC3.Columns = 3; txtBoxC3.ID = ddl2.SelectedValue + "3";
btn1.Text = "click me"; btn1.ID = ddl1.SelectedValue; btn1.Click += btn1_Click;
phDynamic.Controls.Add(btn1);
phDynamic.Controls.Add(txtBoxC1);
phDynamic.Controls.Add(txtBoxC2);
phDynamic.Controls.Add(txtBoxC3);
}
}
}
...
...
...
private void btn1_Click(object sender, EventArgs e)
{
Response.Write(txtBoxC1.Text+txtBoxC2.Text+txtBoxC3.Text);
}
So instead of getting back values from my 3 textboxes, I don't get back anything, and I also lose placeholder controls.

Create a tab for each row found in db

I have a query that selects a table form my db and displays it on some labels, but if the query finds more the one data row it has to display each one of them in a different tab of the form, how can i archive this.
Code:
try
{
mycon.Open();
string querieslabels = "Select *From Alerts where State = #state && Lv =#lv";
oleDbCmd = new OleDbCommand(querieslabels, mycon);
oleDbCmd.Parameters.Add("#state", OleDbType.VarChar, 10).Value = "Open";
oleDbCmd.Parameters.Add("#lv", OleDbType.VarChar, 2).Value = "1";
OleDbDataReader read1;
read1 = oleDbCmd.ExecuteReader();
read1.Read();
state = read1[4].ToString();
if (state != "Closed")
{
lblNum.Text = read1[0].ToString();
lblpress.Text = read1[1].ToString();
txtDescription.Text = read1[2].ToString();
lblDate.Text = read1[3].ToString();
lblOk.Visible = false;
pictureBox2.Visible = false;
mycon.Close();
}
else
{
//Hides labels and other control's
MakeNotVisible();
MessageBox.Show("No alert found");
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
finally
{
mycon.Close();
}
}
What I'm trying to create is some alert system, if there is more than 1 alert it should display in a different tab. Can some one guide me to the solution for this, any help or suggestion is appreciated.
NOTE: I'm using Win Form.
You could create a UserControl, with code that can display one record from a DataTable. Then you can create TabPages and add one new UC to it for each of your rows. Take care not to add too many pages, say no more than 10-15!
Update I just noticed that you are using a DataReader, not a DataTable. No problem, the same solution will worke here, too: Use the added ShowReader method and call it like below..!
Here is an example:
public partial class DataForm : UserControl
{
public DataTable theTable { get; set; }
public DataForm()
{
InitializeComponent();
}
public int showTableRow(int rowIndex)
{
if (theTable == null) return -1;
if (theTable.Rows.Count < rowIndex) return -2;
DataRow row = theTable.Rows[rowIndex];
label1.Text = row[0].ToString();
label2.Text = row[1].ToString();
label3.Text = row[2].ToString();
return 0;
}
public void showReaderRow(OleDbDataReader DR)
{
label1.Text = DR[0].ToString();
label2.Text = DR[1].ToString();
label3.Text = DR[2].ToString();
}
}
For easier access we'll keep a List:
List<DataForm> theDataPages = new List<DataForm>();
Now we can add DataForm pages to the Tab control tabFormPages from the records in a DataTable; here I limit the number to 5:
for (int r = 0; r < DTL.Rows.Count && r < 5; r++)
{
TabPage page = new TabPage( (r+1).ToString("Record #0" ));
DataForm aForm = new DataForm();
aForm.theTable = DTL;
aForm.Parent = page;
aForm.showTableRow(r);
tabFormPages.TabPages.Add(page);
theDataPages.Add(aForm);
}
For use with a DataReader you could write a read loop like this:
while (DR.Read())
{
TabPage page = new TabPage("Alert #"
+ (tabFormPages.TabPages.Count+1).ToString());
DataForm aForm = new DataForm();
aForm.Parent = page;
aForm.showReaderRow(DR);
tabFormPages.TabPages.Add(page);
theDataPages.Add(aForm);
}
First you add the class to your project: Add - Add Usercontrol.
Now you can open it in the Designer and put in all Labels you need as well as the and put a the code. Also flesh out the showRow method to properly display your data in those Labels..
Now you can add such UCs to TabPages in your Tab like I did above.
If you are using a DataTable you can also make one page display a certain record by calling the showRow again:
theDataPages[0].showRow(DTL.Rows.Count - 1);
This will show the last record in the first TabPage.
If you really need to access field on that UC you can create public properties for those fields and access them like so:
public DataTable theTable { get; set; }
public Label Label1 { get; set; }
//..
public DataForm()
{
InitializeComponent();
Label1 = label1;
//..
}
Now you can access the field(s):
if (theDataPages[0].Label1.Text == "Hiho"
theDataPages[0].Label1.BackColor = Color.Green;
Are you using a WinForms application or a WebForms application? You might need an Accordion control (http://www.codeproject.com/Articles/416521/Easy-WinForms-Accordion-Control) or a Tab Control (http://www.c-sharpcorner.com/UploadFile/mahesh/C-Sharp-tabcontrol/) or something similar. You can dynamically create the tabs in them based on the number of rows in your result.

text box autocomplete not working properly

I am facing problem while work on text box autocomplete in window form application. my collection show 50 records on search. but i receive only 2 in textbox suggestion. why? see code .I am doing this work in txtInput_TextChanged event.
private void txtInput_TextChanged(object sender, EventArgs e)
{
string str = txtInput.Text.ToString();
dv = new DataView(dt);
dv.RowFilter = "MedicineName like '%" + str + "%'";
for (int i = 0; i < dv.Count; i++)
{
string name = dv[i]["MedicineName"].ToString();
nameCollection.Add(name);
}
txtInput.AutoCompleteMode = AutoCompleteMode.Suggest;
txtInput.AutoCompleteSource = AutoCompleteSource.CustomSource;
txtInput.AutoCompleteCustomSource = nameCollection;
//textboxMedicine.BorderStyle = BorderStyle.Fixed3D;
//textboxMedicine.ScrollBars = ScrollBars.Vertical;
}
I also set autocomplete and autocompletesource in property window. but still my textbox autocomplete suggestions not working correctly. please help
Use this AutoCompleteMode.SuggestAppend for AutoCompleteMode
txtInput.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
EDIT:
Change like to LIKE
dv.RowFilter = "MedicineName LIKE '%"+str+"%'";

Categories

Resources