Search in A ListBox - c#

HI
I'm trying to put a textbox to search in a listBox.
I have a TextBox: SearchText with this code:
private void SearchText_TextChanged(object sender, EventArgs e)
{
int i = listBox3.FindString(SearchText.Text);
listBox3.SelectedIndex = i;
}
and a ListBox On the Load I have this code
List<string> str = GetListOfFiles(#"D:\\Music\\massive attack - collected");
listBox3.DataSource = str;
listBox3.DisplayMember = "str";
and on selectedIndexChanged :
private void listBox3_SelectedIndexChanged(object sender, EventArgs e)
{
player1.URL = listBox3.SelectedItem.ToString(); // HERE APPEAR THE ERROR "Object reference not set to an instance of an object."
// provaTxt.Text = listBox3.SelectedValue.ToString();
}
When I write down in the SeachText to find a songs I receive an error ("Object reference not set to an instance of an object.") in the line selectedIndexChanged of the ListBox.
Do you know one more way to find in a listBox as my case?
Thanks for your share.
Nice Regards

It sounds like the item wasn't found, so SelectedItem was null; try using:
player1.URL = Convert.ToString(listBox3.SelectedItem);
I believe this handles the null case (altenatively, test for null first).
I'd also be tempted to look in the underlying list:
List<string> items = (List<string>)listbox3.DataSource;
listbox3.SelectedIndex = items.FindIndex(s => s.StartsWith(searchFor));
For example:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
class MyForm : Form
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MyForm());
}
ListBox listbox;
TextBox textbox;
CheckBox multi;
public MyForm()
{
textbox = new TextBox { Dock = DockStyle.Top };
List<string> strings = new List<string> { "abc", "abd", "abed", "ab" };
listbox = new ListBox { Dock = DockStyle.Fill, DataSource = strings };
textbox.KeyDown += textbox_KeyDown;
Controls.Add(listbox);
Controls.Add(textbox);
listbox.SelectedIndexChanged += listbox_SelectedIndexChanged;
listbox.SelectionMode = SelectionMode.MultiExtended;
multi = new CheckBox { Text = "select multiple", Dock = DockStyle.Bottom };
Controls.Add(multi);
}
void listbox_SelectedIndexChanged(object sender, EventArgs e)
{
Text = Convert.ToString(listbox.SelectedItem);
}
void textbox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return)
{
string searchFor = textbox.Text;
List<string> strings = (List<string>)listbox.DataSource;
if (multi.Checked)
{
for (int i = 0; i < strings.Count; i++)
{
listbox.SetSelected(i, strings[i].Contains(searchFor));
}
}
else
{
listbox.ClearSelected();
listbox.SelectedIndex = strings.FindIndex(
s => s.Contains(searchFor));
}
}
}
}

Related

C# how do I make my label from an label array disappear when clicked on?

My code makes 5 labels appear with a random .Left location, you can see it.
I want the particular label to disappear when I click on it, but I don't know how to tell it to my click void.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Label [] kubeliai = new Label [5];
int poz = 100;
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < kubeliai.Length; i++)
{
kubeliai[i] = new Label();
Controls.Add(kubeliai[i]);
Random pos = new Random();
kubeliai[i].Top = 50;
kubeliai[i].Left = poz;
poz += pos.Next(50, 200);
kubeliai[i].BackColor = Color.Red;
kubeliai[i].Height = 20;
kubeliai[i].Width = 20;
kubeliai[i].Click += new EventHandler(kubelio_clickas);
}
}
void kubelio_clickas (object sender, EventArgs e)
{
}
}
The instance of "clicked" label is in sender parameter:
void kubelio_clickas (object sender, EventArgs e)
{
Label clickedLabel = sender as Label;
if (clickedLabel != null) {
clickedLabel.Visible = false;
}
}
Because in .NET Event Handlers by default use object as type of sender you have to cast it to Label first.
I want the particular label to disappear when I click on it
Just set the label's .Visible property to false:
void kubelio_clickas (object sender, EventArgs e)
{
if (sender is Label)
((Label)sender).Visible = false;
}
The object sender is a reference to the object which fired the event. So basically, the sender is the object you are looking for.
You just need to set it invisible:
((Label)sender).Visible = false;

How to display entered string from textbox in ordered list in c#?

I have the following requirement :
There is one text box. Whenever I type a string in textbox and press ENTER, that particular string should be appended to the datagridview and textbox should be cleared. Again the same process repeats.
I am new to C# , any suggestion where to start ?
FYI, Reference Image.
source code :
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public int count = 0;
string[] arr = new string[5];
ListViewItem itm;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
listView1.View = View.Details;
listView1.GridLines = true;
listView1.FullRowSelect = true;
//Add column header
listView1.Columns.Add("List 1", 50);
listView1.Columns.Add("List 2", 50);
listView1.Columns.Add("List 3", 50);
listView1.Columns.Add("List 4", 50);
listView1.Columns.Add("List 5", 50);
}
private void button1_Click(object sender, EventArgs e)
{
string productName = null;
string price = null;
string quantity = null;
productName = listView1.SelectedItems[0].SubItems[0].Text;
price = listView1.SelectedItems[0].SubItems[1].Text;
quantity = listView1.SelectedItems[0].SubItems[2].Text;
MessageBox.Show(productName + " , " + price + " , " + quantity);
}
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
//MessageBox.Show("hii");
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Enter)
{
// MessageBox.Show(count.ToString());
arr[count] = textBox1.Text;
//if (count == 0)
//{
itm = new ListViewItem(arr);
//}
listView1.Items.Add(itm);
// MessageBox.Show(arr.ToString());
if (count < 4)
{
count = count + 1;
}
else if(count == 4)
{
count = 0;
}
}
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
}
}
}
here i have used listbox. so my output should be like reference image.
Adding the Insert to DataGrid functionality for the Answer by General-Doomer.
void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
TextBox tb = (TextBox)sender;
this.dataGridView1.Rows.Add(tb.Text);
tb.Clear();
}
}
EDIT :
//global variable and preferably initialize in the constructor or OnLoad Event
List<string> mystringlist = new List<string>();
void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
TextBox tb = (TextBox)sender;
if(mystringlist.Count >= 5)
{
this.dataGridView1.Rows.Add(mystringlist.ToArray());
mystringlist.Clear();
}
mystringlist.Add(tb.Text);
tb.Clear();
}
}
Complete sample form code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinForm
{
public partial class frmMain : Form
{
/// <summary>
/// form constructor
/// </summary>
public frmMain()
{
InitializeComponent();
}
private ListView listView;
private TextBox textBox;
/// <summary>
/// form load
/// </summary>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// create list view
listView = new ListView()
{
Location = new Point(8, 8),
Size = new Size(this.ClientSize.Width - 16, this.ClientSize.Height - 42),
Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom,
View = View.List,
};
listView.Columns.Add(new ColumnHeader() { Text = "Header" });
listView.Sorting = SortOrder.Ascending;
this.Controls.Add(listView);
// create textbox
textBox = new TextBox()
{
Location = new Point(8, listView.Bottom + 8),
Size = new Size(this.ClientSize.Width - 16, 20),
Anchor = AnchorStyles.Left | AnchorStyles.Bottom,
Text = "Write some text here and press [Enter]"
};
this.Controls.Add(textBox);
// bind textbox KeyDown event
textBox.KeyDown += textBox_KeyDown;
}
/// <summary>
/// KeyDown event handler
/// </summary>
void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
// [Enter] key pressed
TextBox tb = (TextBox)sender;
string text = tb.Text;
if (listView.Items.ContainsKey(text))
{
// item already added
MessageBox.Show(string.Format("String '{0}' already added", text));
}
else
{
// add new item
listView.Items.Add(text, text, 0);
listView.Sort();
tb.Clear();
}
}
}
}
}
Result:

Cannot Add Dynamically Generated Textbox's Text To A List (C#)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Mod
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int c = 0;
private void button1_Click(object sender, EventArgs e)
{
TextBox txtRun = new TextBox();
txtRun.Name = "txtDynamic" + c++;
txtRun.Location = new System.Drawing.Point(20, 18 + (20 * c));
txtRun.Size = new System.Drawing.Size(200,15);
this.Controls.Add(txtRun);
}
private void button2_Click(object sender, EventArgs e)
{
List<string>tilelocation = List<string>();
tilelocation.Add(); //What goes in this method's arguments?
}
}
}
Here is my code. Button1 creates a theoretically infinite # of textboxes, but I wish to add the text in these dynamically generated textboxes to a list. How can this be done?
[EDIT]
And how can I display them all in a messagebox, each on separate lines?
You need to keep a reference to the control.
The other secret is that you have to keep it in the ViewState so it's available between post backs.
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
int c = 0;
private List<TextBox _lstTextBoxList;
public List<TextBox> lstTextBoxList {
get {
if(_lstTextBoxList == null) {
_lstTextBoxList = ViewState["lstTextBoxList"] as List<TextBox>;
}
return _lstTextBoxList;
}
set { ViewState["lstTextBoxList"] = _lstTextBoxList = value; }
}
private void button1_Click(object sender, EventArgs e) {
TextBox txtRun = new TextBox();
txtRun.Name = "txtDynamic" + c++;
txtRun.Location = new System.Drawing.Point(20, 18 + (20 * c));
txtRun.Size = new System.Drawing.Size(200,15);
this.Controls.Add(txtRun);
lstTextBoxList.Add(txtRun);
}
private void button2_Click(object sender, EventArgs e) {
// Not sure of your goal here:
List<string> tilelocation = List<string>();
tilelocation.Add(lstTextBoxList[lstTextBoxList.Count - 1]);
// I would assume you wanted this:
List<string> strValues = lstTextBoxList.Select<TextBox,string>(t => t.Text).ToList();
}
}
but I wish to add the text in these dynamically generated textboxes to
a list. How can this be done?
You should use new List<string> like:
private void button2_Click(object sender, EventArgs e)
{
List<string> tilelocation = new List<string>();
foreach(TextBox tb in this.Controls.OfType<TextBox>().Where(r=> r.Name.StartsWith("txtDynamic"))
titlelocation.Add(tb.Text);
//if you want a string out of it.
string str = string.Join(",", titlelocation);
MessageBox.Show(str);
}
EDIT: For each text on new line use:
string str = string.Join(Environment.NewLine, titlelocation);
MessageBox.Show(str);
I don't know why you want to use a seperate button2 click event to add the text. Why don't you use a global variable tilelocation, and add the text to this list in the button1_click event? Something like:
txtRun.Text=Your Text;
tilelocation.add(Your Text);
If you want to display them in a message box, then add codes:
string str="";
foreach(text in tilelocation)
{
str+=text;
}
MessageBox.Show(str);

Get values of dynamically created controls (comboboxes)

I've got panel on which by default are two comboboxes and one "+" button which creates two new combo boxes bellow the first one, I can create multiple (n) rows with two combo boxes and everything is working, I just can't figure out how to get values of those boxes?
Here's code for creating (adding) controls
private void btnCreateFilter_Click(object sender, EventArgs e)
{
y += comboBoxHeight;
ComboBox cb = new ComboBox();
cb.Location = new Point(x, y);
cb.Size = new Size(121, 21);
panelFiltri.Controls.Add(cb);
yDrugi += comboBoxHeight;
ComboBox cbSql = new ComboBox();
cbSql.Location = new Point(xDrugi, yDrugi);
cbSql.Size = new Size(121, 21);
panelFiltri.Controls.Add(cbSql);
btnCancel.Location = new Point(btnCancel.Location.X, btnCancel.Location.Y + 25);
btnSaveFilter.Location = new Point(btnSaveFilter.Location.X, btnSaveFilter.Location.Y + 25);
}
And here's code where I'm lost:
private void btnSaveFilter_Click(object sender, EventArgs e)
{
int i;
foreach (Control s in panelFiltri.Controls)
{
//GOT LOST
}
}
You can get the text in the ComboBox as
private void btnSaveFilter_Click(object sender, EventArgs e)
{
foreach (Control control in panelFiltri.Controls)
{
if (control is ComboBox)
{
string valueInComboBox = control.Text;
// Do something with this value
}
}
}
I don't really know what you're trying to achieve... Maybe this will help you along...
private void btnSaveFilter_Click(object sender, EventArgs e)
{
foreach (ComboBox comboBox in panelFiltri.Controls)
{
var itemCollection = comboBox.Items;
int itemCount = itemCollection.Count; // which is 0 in your case
}
}

How can I add a context menu to a ListBoxItem?

I have a ListBox and I want to add a context menu to each item in the list. I've seen the "solution" to have the right click select an item and suppress the context menu if on white space, but this solution feels dirty.
Does anyone know a better way?
Just to elaborate a little further to what Frans has said...Even though the ListBox owns the ContextMenuStrip, you can still customize the items in the menu strip at the time it's opening. Thus customizing it's contents based on the mouse position within the listbox.
The example below selects the item in the listbox based on a right mouse click and then customizes a context menu strip based on the item the user right-clicked on. This is a simple example but should get you going: Add a listbox to a form and add this code:
#region Private Members
private ContextMenuStrip listboxContextMenu;
#endregion
private void Form1_Load( object sender, EventArgs e )
{
//assign a contextmenustrip
listboxContextMenu = new ContextMenuStrip();
listboxContextMenu.Opening +=new CancelEventHandler(listboxContextMenu_Opening);
listBox1.ContextMenuStrip = listboxContextMenu;
//load a listbox
for ( int i = 0; i < 100; i++ )
{
listBox1.Items.Add( "Item: " + i );
}
}
private void listBox1_MouseDown( object sender, MouseEventArgs e )
{
if ( e.Button == MouseButtons.Right )
{
//select the item under the mouse pointer
listBox1.SelectedIndex = listBox1.IndexFromPoint( e.Location );
if ( listBox1.SelectedIndex != -1)
{
listboxContextMenu.Show();
}
}
}
private void listboxContextMenu_Opening( object sender, CancelEventArgs e )
{
//clear the menu and add custom items
listboxContextMenu.Items.Clear();
listboxContextMenu.Items.Add( string.Format( "Edit - {0}", listBox1.SelectedItem.ToString() ) );
}
Hope that help.
This way the menu will pop up next to the mouse
private string _selectedMenuItem;
private readonly ContextMenuStrip collectionRoundMenuStrip;
public Form1()
{
var toolStripMenuItem1 = new ToolStripMenuItem {Text = "Copy CR Name"};
toolStripMenuItem1.Click += toolStripMenuItem1_Click;
var toolStripMenuItem2 = new ToolStripMenuItem {Text = "Get information on CR"};
toolStripMenuItem2.Click += toolStripMenuItem2_Click;
collectionRoundMenuStrip = new ContextMenuStrip();
collectionRoundMenuStrip.Items.AddRange(new ToolStripItem[] {toolStripMenuItem1, toolStripMenuItem2 });
listBoxCollectionRounds.MouseDown += listBoxCollectionRounds_MouseDown;
}
private void toolStripMenuItem2_Click(object sender, EventArgs e)
{
var info = GetInfoByName(_selectedMenuItem);
MessageBox.Show(info.Name + Environment.NewLine + info.Date);
}
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
Clipboard.SetText(_selectedMenuItem);
}
private void myListBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Right) return;
var index = myListBox.IndexFromPoint(e.Location);
if (index != ListBox.NoMatches)
{
_selectedMenuItem = listBoxCollectionRounds.Items[index].ToString();
collectionRoundMenuStrip.Show(Cursor.Position);
collectionRoundMenuStrip.Visible = true;
}
else
{
collectionRoundMenuStrip.Visible = false;
}
}
There's no other way: the context menu isn't owned by the item in the listbox but by the listbox itself. It's similar to the treeview control which also owns the context menu instead of the treenode. So whenever an item in the listbox is selected, set the context menu of the listbox according to the selected item.
And Here it is My Solution :
listBox_Usernames.ContextMenuStrip = contextMenuStripRemove;
listBox_Usernames.MouseUp += new MouseEventHandler(listBox_Usernames_MouseUp);
void listBox_Usernames_MouseUp(object sender, MouseEventArgs e)
{
int index = listBox_Usernames.IndexFromPoint(e.Location);
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
if (index != ListBox.NoMatches)
{
if (listBox_Usernames.SelectedIndex == index)
{
listBox_Usernames.ContextMenuStrip.Visible = true;
}
else
{
listBox_Usernames.ContextMenuStrip.Visible = false;
}
}
else
{
listBox_Usernames.ContextMenuStrip.Visible = false;
}
}
else
{
listBox_Usernames.ContextMenuStrip.Visible = false;
}
}
In XAML it shows like this:
<ListBox>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Add User..."/>
<MenuItem Header="Edit..."/>
<MenuItem Header="Disable"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
In one line of code (more for binding):
var datasource = new BindingList<string>( new List<string>( new string[] { "item1" } ) );
listbox.DataSource = datasource ;
listbox.ContextMenu = new ContextMenu(
new MenuItem[] {
new MenuItem("Delete",
new EventHandler( (s,ev) =>
datasource.Remove(listbox.SelectedItem.ToString())
)
)
});
private void buttonAdd_Click(object sender, EventArgs e)
{
datasource.Add( textBox.Text );
}
If its just a question of enabling or disabling context menu items, it might be more efficient to only do it when the context menu is launched rather than every time the list box selection changes:
myListBox.ContextMenu.Popup += new EventHandler(myContextPopupHandler);
private void myContextPopupHandler(Object sender, System.EventArgs e)
{
if (SelectedItem != null)
{
ContextMenu.MenuItems[1].Enabled = true;
ContextMenu.MenuItems[2].Enabled = true;
}
else
{
ContextMenu.MenuItems[1].Enabled = false;
ContextMenu.MenuItems[2].Enabled = false;
}
}
this one is best...
using System.Windows.Forms;
ContextMenuStrip menu;
this.menu.Items.AddRange(new ToolStripItem[] { this.menuItem });
this.listBox.MouseUp += new MouseEventHandler(this.mouse_RightClick);
private void mouse_RightClick(object sender, MouseEventArgs e)
{
int index = this.listBox.IndexFromPoint(e.Location);
if (index != ListBox.NoMatches)
{
menu.Visible = true;
}
else
{
menu.Visible = false;
}
}
//Create and Initialize the contextMenuStrip component
contextMenuStrip_ListaAulas = new ContextMenuStrip();
//Adding an Item
contextMenuStrip_ListaAulas.Items.Add("Modificar");
//Binding the contextMenuStrip with the ListBox
listBox_Aulas.ContextMenuStrip = contextMenuStrip_ListaAulas;
//The solution below
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
//select the item under the mouse pointer
listBox_Aulas.SelectedIndex = listBox_Aulas.IndexFromPoint(e.Location);
//if the selected index is an item, binding the context MenuStrip with the listBox
if (listBox_Aulas.SelectedIndex != -1)
{
listBox_Aulas.ContextMenuStrip = contextMenuStrip_ListaAulas;
}
//else, untie the contextMenuStrip to the listBox
else
{
listBox_Aulas.ContextMenuStrip = null;
}
}
I do like this, this works great and fast for me.
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
if (Listbox.SelectedItem == null)
e.Cancel = true;
}

Categories