How to select ListView items programmatically? - c#

I've been looking for a solution since this morning, and even after reading tons of other threads on this subject it doesn't work for me. Without further ados let's check this code sample:
// Create Dictionary, Keys = Ids, Values = Names
Dictionary<int, string> ff_names = new Dictionary<int, string>();
ff_names.Add(0, "Cloud");
ff_names.Add(1, "Barret");
ff_names.Add(2, "Tifa");
ff_names.Add(3, "Aerith");
ff_names.Add(4, "Red XIII");
// Populating ListView
foreach( KeyValuePair<int, string> dict in ff_names )
{
ListViewItem lvi = new ListViewItem(dict.Key.ToString());
lvi.SubItems.Add(dict.Value);
listView1.Items.Add(lvi);
}
// Test Item Selection
listView1.Focus();
listView1.Select();
listView1.Items[0].Focused = true;
listView1.Items[0].Selected = true;
string s = listView1.SelectedItems.Count.ToString();
label1.text = s; // sadly, it's equal to 0;
textBox1.Text = listView1.SelectedItems[0].SubItems[0].Text; // program will crash
Technically, I would like to selection an item of the ListView and display one of its element in a textbox. It works when I select an item manually, but when I try to select programmatically like shown above it doesn't want to select anything, the SelectedItems count is equal to zero...
Thank you for you help and hope someone can find a solution to what I'm missing!

Here you go. You'll have to make the event handler for listView1_SelectedIndexChanged.
public Form1() {
InitializeComponent();
listView1.View = View.Details;
listView1.Columns.Add("Key");
listView1.Columns.Add("Value");
LoadListView();
}
private void LoadListView() {
// Create Dictionary, Keys = Ids, Values = Names
Dictionary<int, string> ff_names = new Dictionary<int, string>();
ff_names.Add(0, "Cloud");
ff_names.Add(1, "Barret");
ff_names.Add(2, "Tifa");
ff_names.Add(3, "Aerith");
ff_names.Add(4, "Red XIII");
// Populating ListView
foreach (KeyValuePair<int, string> dict in ff_names) {
ListViewItem lvi = new ListViewItem(new string[] { dict.Key.ToString(), dict.Value });
listView1.Items.Add(lvi);
}
// Test Item Selection
listView1.Focus();
listView1.Select();
listView1.Items[0].Focused = true;
listView1.Items[0].Selected = true;
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e) {
if (listView1.SelectedItems.Count > 0) {
label1.Text = (string)listView1.SelectedItems[0].Text; // sadly, it's equal to 0;
textBox1.Text = (string)listView1.SelectedItems[0].SubItems[1].Text;
}
}

I think drankin2112's answer is useful, but you say it doesn't work, so I complement it, hope this could be helpful to you.
To finish your work, you need to do three things as follow:
1.load data and fill in listview;
2.define the process method when listview's selected item changed;
3.give a test method to programmatically select different item, the you can see result.
my sample code is below:
public MainWindow()
{
InitializeComponent();
listView1.View = View.Details;
listView1.Columns.Add("Key");
listView1.Columns.Add("Value");
this.listView1.FullRowSelect = true;
//register the process event
this.listView1.SelectedIndexChanged += this.listView1_SelectedIndexChanged;
//load data
LoadListView();
//test item selection
ToSelectItem(0);
}
void ToSelectItem(int itemIndex)
{
if (itemIndex > listView1.Items.Count - 1)
return;
listView1.Focus();
listView1.Select();
listView1.Items[itemIndex].Focused = true;
listView1.Items[itemIndex].Selected = true;
}
private void LoadListView()
{
// Create Dictionary, Keys = Ids, Values = Names
Dictionary<int, string> ff_names = new Dictionary<int, string>();
ff_names.Add(0, "Cloud");
ff_names.Add(1, "Barret");
ff_names.Add(2, "Tifa");
ff_names.Add(3, "Aerith");
ff_names.Add(4, "Red XIII");
// Populating ListView
foreach (KeyValuePair<int, string> dict in ff_names)
{
ListViewItem lvi = new ListViewItem(new string[] { dict.Key.ToString(), dict.Value });
listView1.Items.Add(lvi);
}
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
{
label1.Text = (string)listView1.SelectedItems[0].Text; // sadly, it's equal to 0;
textBox1.Text = (string)listView1.SelectedItems[0].SubItems[1].Text;
}
}

Related

Advanced item search in combobox C#

I wrote a program with C #
I have a combo box whose items are Binding from the database.I use AutoCompleteMode and AutoCompleteSource to search the combo box.But only when filtering does it find words whose first letter is the same as the input letter.While I need All items that contain these letters displayed.Is there a solution to this problem?
maybe this helps
// Example data
string[] data = new string[] {
"Absecon","Abstracta","Abundantia","Academia","Acadiau","Acamas",
"Ackerman","Ackley","Ackworth","Acomita","Aconcagua","Acton","Acushnet",
"Acworth","Ada","Ada","Adair","Adairs","Adair","Adak","Adalberta","Adamkrafft",
"Adams"
};
public Form1()
{
InitializeComponent();
}
private void comboBox1_TextChanged(object sender, EventArgs e)
{
HandleTextChanged();
}
// Handle Text Box that you Fill
private void HandleTextChanged()
{
var txt = comboBox1.Text;
var list = from d in data
where d.Tolower().Contains(comboBox1.Text.ToLower())
select d;
if (list.Count() > 0)
{
comboBox1.DataSource = list.ToList();
//comboBox1.SelectedIndex = 0;
var sText = comboBox1.Items[0].ToString();
comboBox1.SelectionStart = txt.Length;
comboBox1.SelectionLength = sText.Length - txt.Length;
comboBox1.DroppedDown = true;
return;
}
else
{
comboBox1.DroppedDown = false;
comboBox1.SelectionStart = txt.Length;
}
}

How to search file and display it in list box?

I am stuck with the project C# and I don't know how to solve it. I have a text file "cars.txt" and it has this information:
1950
Nissan Sentra
Ford Focus
1951
Mazda5
Mazda3
Toyota
1952
Chevy
I have to have 2 list boxes and one button. The first list box supposed to search through the file and populate years and when user select year and click on the button and it displays the corresponding cars models for this specific year. I have thoughts about using StreamReader but I don't know how to start.
Your help appreciated
Create a dictionary of string lists that will contain car lists with the year a key as well as a list for the years:
private readonly Dictionary<int, List<string>> _carsByYear =
new Dictionary<int, List<string>>();
private readonly List<int> _years = new List<int>();
Then you can fill it with
List<string> cars = null;
foreach (string line in File.ReadLines(#"C:\Users\Me\cars.txt")) {
if (!String.IsNullOrWhiteSpace(line)) {
if (Int32.TryParse(line, out int year)) { // We have a year
if (_carsByYear.TryGetValue(year, out var existingList)) {
cars = existingList;
} else {
// Add a new list with year as the key
_years.Add(year);
cars = new List<string>();
_carsByYear.Add(year, cars);
}
} else { // We have a car
cars.Add(line);
}
}
}
Now you can assign _years to the DataSource of the first ListBox. You can get the selected year (SelectedIndexChanged event) with
int year = (int)listBox1.SelectedItem;
With this year, you can get the cars list with
var selectedCarList = _carsByYear[year];
Assign it to the DataSource of the second ListBox.
now the is no error but nothing displayed. This is a very challenging
assignment. everyone in my class is stuck.
Works fine for me. Here's a variation with some examples of how you could use it:
private readonly SortedList<int, SortedSet<string>> _carsByYear = new SortedList<int, SortedSet<string>>();
private void button1_Click(object sender, EventArgs e)
{
SortedSet<string> cars = null;
string fileName = System.IO.Path.Combine(
System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"cars.txt");
foreach (string line in File.ReadLines(fileName))
{
if (!String.IsNullOrWhiteSpace(line))
{
if (Int32.TryParse(line, out int year))
{ // We have a year
if (!_carsByYear.ContainsKey(year))
{
cars = new SortedSet<string>();
_carsByYear.Add(year, cars);
}
else
{
cars = _carsByYear[year];
}
}
else
{ // We have a car
if (!cars.Contains(line))
{
cars.Add(line);
}
}
}
}
listBox1.DataSource = _carsByYear.Keys.ToList();
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listBox1.SelectedIndex != -1)
{
listBox2.DataSource = _carsByYear[(int)listBox1.SelectedItem].ToList();
}
}
private void button2_Click(object sender, EventArgs e)
{
if (listBox1.SelectedIndex != -1 && listBox2.SelectedIndex != -1)
{
int year = (int)listBox1.SelectedItem;
string car = listBox2.SelectedItem.ToString();
label1.Text = year.ToString();
label2.Text = car;
}
else
{
label1.Text = "";
label2.Text = "";
}
}
If you still can't get it to work, give MORE DETAILS about the contents of the file and how you're supposed to use it in your interface.

Winforms insert image into ListView / ImageList at index

Winforms, C#, VS2017
ImageList does not have an Insert method (however ListViewItemCollection does). I have tried a few different ways to insert a new image into the middle of a ListView and it's LargeImageList, but not getting it to work quite properly.
Anyone have any tried and true code that works properly?
This is what I have, but the images don't get synced properly to the items in the list.
protected void InsertThumbnail(string key, string keySelected)
{
var newImageList = new ImageList()
{
ImageSize = new Size(thumbWidth, thumbHeight)
};
var itemNew = new ListViewItem();
var foundSelected = false;
//lvAllPages.BeginUpdate();
for (int i = 0; i < lvAllPages.Items.Count; i++)
{
var item = lvAllPages.Items[i];
newImageList.Images.Add(item.Tag.ToString(), lvAllPages.LargeImageList.Images[i]);
if (item.Tag.ToString() == keySelected)
{
var image = batch.GetThumbnail(key);
newImageList.Images.Add(key, image);
itemNew = new ListViewItem()
{
BackColor = Color.Aquamarine,
ImageIndex = i,
Tag = key,
};
if (isLocal)
itemNew.Text = $"{GetFileName(key)} (insert) - {itemNew.ImageIndex}";
foundSelected = true;
}
if (foundSelected)
{
item.ImageIndex = item.ImageIndex + 1;
if (isLocal)
item.Text = $"{GetFileName(item.Tag.ToString())} - {item.ImageIndex}";
}
}
lvAllPages.LargeImageList.Dispose();
lvAllPages.LargeImageList = newImageList;
lvAllPages.Items.Insert(itemNew.ImageIndex, itemNew);
}
One more related thing, but not pertinent to the problems I am having. For anyone looking at this question and having similar issues, this helped with the issue of sorting items after inserting a new one. Default behavior when you insert a new ListViewItem at a given index, it will appear at the bottom of the list. I found this handy class to keep items sorted by index, which solved that problem:
class CompareByIndex : IComparer
{
private readonly ListView _listView;
public CompareByIndex(ListView listView)
{
this._listView = listView;
}
public int Compare(object x, object y)
{
int i = this._listView.Items.IndexOf((ListViewItem)x);
int j = this._listView.Items.IndexOf((ListViewItem)y);
return i - j;
}
}
And in the form load:
lvAllPages.ListViewItemSorter = new CompareByIndex(lvAllPages);
Obviously, that's a design decision. ImageList.Images is a ImageCollection and as such, it implements the IList interface.
Unfortunately, the Insert() method is allowed to throw a NotSupportedException. And that's what the list will do when used like a IList:
((IList)imageList.Images).Insert(5, new Bitmap(10,10));
System.NotSupportedException: 'Specified method is not supported.'
In order to have the images shown in a specific order, use the Add() method which takes the key:
imageList.Images.Add("1", new Bitmap(100,100));
That should also enable you to replace the image:
imageList.Images.RemoveByKey("1");
imageList.Images.Add("1", new Bitmap(200,200));
For that to work, you need to set the Sorting property:
listView1.Sorting = SortOrder.Ascending;
For storing additional information like path etc. use anotther data structure with the same key.
Here's the code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
ImageList imageList = new ImageList();
Dictionary<string, Metadata> metadata = new Dictionary<string, Metadata>();
private string dir = #"H:\temp";
private void button1_Click(object sender, EventArgs e)
{
// You would set this in the designer, probably
listView1.Sorting = SortOrder.Ascending;
listView1.View = View.LargeIcon;
listView1.LargeImageList = imageList;
// Make sure we start from the beginning
listView1.Items.Clear();
imageList.Images.Clear();
metadata.Clear();
// Add items
for (int i = 0; i < 10; i++)
{
var filename = "1 ("+(i+1)+").png"; // Just strange names I have
var fullFileName = Path.Combine(dir, filename);
imageList.Images.Add(i.ToString(), Bitmap.FromFile(fullFileName));
metadata.Add(i.ToString(), new Metadata{Path = fullFileName});
listView1.Items.Add(i.ToString(), "Image " + i, i.ToString());
}
// Update view
listView1.Refresh();
listView1.Invalidate();
}
private void button2_Click(object sender, EventArgs e)
{
for (int i = 3; i < 6; i++)
{
var filename = "1 ("+(i+2)+").png";
var fullFileName = Path.Combine(dir, filename);
// Change image
imageList.Images.RemoveByKey(i.ToString());
imageList.Images.Add(i.ToString(), Bitmap.FromFile(fullFileName));
// Match metadata and image
metadata[i.ToString()] = new Metadata{Path = fullFileName};
}
listView1.Refresh();
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
{
var key = listView1.SelectedItems[0].ImageKey;
label1.Text = metadata[key].Path;
}
else
{
label1.Text = "No image selected";
}
}
}
internal class Metadata
{
internal string Path;
}

move items within a listbox that filled from list of keyvaluepair

I have a list of integers.5 items max.These 5 integers shows 5 indexes of listbox items.I want to move this items in the first 5 places of this listbox.This listbox is filled from a list with this code
uList.Add(new KeyValuePair<int, string>(item.Id, item.Name));
listBoxHome.DataSource = uList;
listBoxHome.DisplayMember = "Value";
listBoxHome.ValueMember = "Key";
indexes is the list of integers refer to index of items.
game.listBoxHome.BeginUpdate();
for (int i = 0; i < 5; i++)
{
foreach (int PlayingInd in indexes)
{
HomeList.Insert(i, HomeList[PlayingInd]);
HomeList.RemoveAt(PlayingInd);
}
}
game.listBoxHome.DataSource = HomeList;
game.listBoxHome.DisplayMember = "Value";
game.listBoxHome.ValueMember = "Key";
game.listBoxHome.EndUpdate();
I use this code to one form:
public void button7_Click(object sender, EventArgs e)
{
Sub sub = new Sub();
foreach (ListItem item in listBox2.Items)
{
uList.Add(new KeyValuePair<int, string>(item.Id, item.Name));
}
sub.HomeList = uList;
}
And in the other form:
private BindingList<KeyValuePair<int, string>> Homelist;
public BindingList<KeyValuePair<int, string>> GetHomelist
{
get { return Homelist; }
set { Homelist = value; }
}
private void button2_Click(object sender, EventArgs e)
{
BindingList<int> indexes = new BindingList<int>();
foreach (int indexChecked in checkedListBox1.CheckedIndices)
{
indexes.Add(indexChecked);
}
Game game = new Game();
foreach (int PlayingInd in indexes)
{
Homelist.Insert(0, Homelist[PlayingInd]);
Homelist.RemoveAt(PlayingInd + 1);
}
game.GetHomelist = Homelist;
this.Close();
}
solved

How to find toolstripmenuItem with name

I have set visible property of my menuStrip1 items to false as
foreach (ToolStripMenuItem itm in menuStrip1.Items)
{
itm.Visible = false;
}
Now I know the Names of toolStripMenuItem and dropDownItem of the menustrip1. How to can I activate the required toolStripMenuItem and dropDownItem.
I have
string mnItm = "SalesToolStripMenuItem";
string ddItm = "invoiceToolStripMenuItem";
Now I want to set visible true to these two(toolStripMenuItem and dropDownItem) items. How can I do that? I know those names only.
Simply use those names to get the actual item via MenuStrip.Items indexer:
ToolStripMenuItem menuItem = menuStrip1.Items[mnItm] as ToolStripMenuItem;
ToolStripDropDownMenu ddItem = menuStrip1.Items[ddItm] as ToolStripDropDownMenu;
You can use
menuStrip1.Items[mnItm].Visible = true;
menuStrip1.Items[ddItm].Visible = true;
or if you want to set Visible to multiple toolstrip items:
string [] visibleItems = new [] {"SalesToolStripMenuItem", "invoiceToolStripMenuItem"};
foreach (ToolStripMenuItem item in menuStrip1.Items)
{
if (visibleItems.Contains(item.Name))
{
item.Visible = false;
}
}
Hope it helps
You're looking for ToolStripItemCollection.Find method.
var items = menustrip.Items.Find("SalesToolStripMenuItem", true);
foreach(var item in items)
{
item.Visible = false;
}
second parameter says whether or not to search the childrens.
You should try something like this:
string strControlVal ="somecontrol"; //"SalesToolStripMenuItem" or "invoiceToolStripMenuItem" in your case
foreach (ToolStripMenuItem item in menuStrip1.Items)
{
if (strControlVal == item.Name)
{
item.Visible = false;
}
}
Initialize strControlVal string on your discretion where you need it.
If i get your question you are trying to disable other than the above two mentioned toolstrip items. Since you know the name of the menu items a slight change in code can get you along
foreach (ToolStripMenuItem itm in menuStrip1.Items)
{
if(itm.Text !="SalesToolStripMenuItem" || itm.Text !="invoiceToolStripMenuItem")
{
itm.Visible = false;
}
}
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
string MenuItemName = sender.ToString()
}

Categories