So I have a class called Person. Each Person can have a Name, Age and Email. And I have about 50 Person objects stored in a list called PersonList. Which I defined like this:
List<Person> PersonList = new List<Person>();
The array looks something like this:
PersonList = {
{
name: 'John',
age: 30,
email: 'John#email.com'
},
{
name: 'Bill',
age: 55,
email: 'Bill#email.com'
}
}
I then loop through this and add each of their Name in to a ListBox:
foreach (var Person in PersonList)
{
ListBox.Items.Add(Person.Name);
}
Please note: All names are unique.
What I want to do now, is that when I select a name in the ListBox, I want their Name, Age and Email to be displayed in a label called Label1. Currently, I accomplish this by looping through the PersonList and checking for a name that matches the selected ListBox item's text.
private void ListBox_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (var Person in PersonList)
{
if (Person.Name == ListBox.SelectedItem.ToString())
{
Label1.Text = "Name: " + Person.Name + Environment.NewLine +
"Age: " + Person.Age + Environment.NewLine +
"Email: " + Person.Email;
}
}
}
It works, but is this the correct way of doing it? I feel like constantly looping through the PersonList to compare names could be bad for the performance. What if PersonList contained thousands of objects?
I also wonder if there is a better way to insert all the Person.Name in to the ListBox? Or is looping the way to go? I know about AddRange, but can I do that on just the Person.Name somehow? Note: I only want to add their names in to the ListBox.
What would you do?
You can fill the listbox directly with the list, and the selection of the item can be done in 3 ways, see the code:
public class Pessoa
{
public string Nome { get; set; }
public string Email { get; set; }
public override string ToString()
{
return this.Nome.ToString();
}
}
List<Pessoa> lista = new List<Pessoa>();
private void Form1_Load(object sender, EventArgs e)
{
lista.Add(new Pessoa() { Nome = "Rovann1", Email = "Teste1#Teste.com" });
lista.Add(new Pessoa() { Nome = "Rovann2", Email = "Teste2#Teste.com" });
lista.Add(new Pessoa() { Nome = "Rovann3", Email = "Teste3#Teste.com" });
listBox1.DisplayMember = "Nome";
listBox1.DataSource = lista;
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
label1.Text = "Select one item";
//1
if (listBox1.SelectedItem != null)
{
label1.Text = ((Pessoa)listBox1.SelectedItem).Email;
}
//2
Pessoa p = lista.Find(x => x.Nome == listBox1.SelectedItem.ToString());
if (p != null)
label1.Text = p.Email;
//3
if (listBox1.SelectedIndex >= 0)
label1.Text = lista[listBox1.SelectedIndex].Email;
}
Related
I have a listbox populated by products stored in an SQLite DB. The listbox is populated like so:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
string navigatedFrom;
base.OnNavigatedTo(e);
navigatedFrom = (string)e.Parameter;
if (navigatedFrom == "main")
{
var products = new ObservableCollection<Product>(data.GetProducts().ToList());
foreach (var product in products)
{
ListBox.Items.Add("Product Name: " + product.ProductName + " Price: " + product.Price + " Quantity: " + product.Quantity);
}
}
else
{
}
}
and the listbox selection is handled like this:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var product = ListBox.SelectedItem as Product;
if (product != null)
{
Frame.Navigate(typeof(DetailsPage), product.Id);
}
ListBox.SelectedIndex = -1;
}
When a product is selected from the listbox the app should navigate to the details page which shows all of the details from the selected product object. My problem occurs when I select a product from the list, the product object is always null. How can I make sure the product object is populated in the correct format with the correct information?
change this:
foreach (var product in products)
{
ListBox.Items.Add("Product Name: " + product.ProductName + " Price: " + product.Price + " Quantity: " + product.Quantity);
}
to
foreach (var product in products)
{
ListBox.Items.Add(product);
}
example Product class:
public class Product
{
public string ProductName { get; private set; }
public string Price { get; private set; }
public string Quantity { get; private set; }
public override string ToString()
{
return $"Product Name: {this.ProductName} Price: {this.Price} Quantity: {this.Quantity}";
}
}
I was wondering how I properly can populate the labels in my form with the information from the selected preset item found in the 'right-click' context menu? I'm currently populating the context menu with the 'name' of each class 'product'. I'd like to then fill in the labels corresponding to the item selected by the users right-click menu. The context menu items will change dynamically as items get added to the list.
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 rcMenu
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Product newProductA = new Product();
newProductA.Name = "Ice Cream";
newProductA.Category = "Dessert";
newProductA.Price = "Free";
productList.Add(newProductA);
Product newProductB = new Product();
newProductB.Name = "Cherries";
newProductB.Category = "Produce";
newProductB.Price = "$10.00";
productList.Add(newProductB);
Product newProductC = new Product();
newProductC.Name = "Soda";
newProductC.Category = "Beverage";
newProductC.Price = "$1.99";
productList.Add(newProductC);
}
public static List<Product> productList = new List<Product>();
public class Product
{
public String Name { get; set; }
public String Category { get; set; }
public String Price { get; set; }
}
private void SelectedPreset(object sender, EventArgs e)
{
label1.Text = "Product Name: " + "SELECTED";
label2.Text = "Product Category: " + "SELECTED";
label3.Text = "Product Price: " + "SELECTED";
}
private void contextMenuStrip1_Opened(object sender, EventArgs e)
{
(contextMenuStrip1.Items[0] as ToolStripMenuItem).DropDownItems.Clear();
foreach (var p in productList)
{
var itemName = p.Name;
(contextMenuStrip1.Items[0] as ToolStripMenuItem).DropDownItems.Add(itemName, null, SelectedPreset);
}
}
}
}
First subscribe to the Opening event and place the code like this:
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
if(contextMenuStrip1.Items.Count > 0)
contextMenuStrip1.Items.Clear();
foreach (var p in productList)
{
var itemName = p.Name;
contextMenuStrip1.Items.Add(itemName);
}
e.Cancel = false;
}
Next subscribe to the ItemClicked event and place the code like this:
private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
Product p = productList.Find(i => i.Name == e.ClickedItem.Text);
//just in case its null...
if(p != null)
{
label1.Text = "Product Name: " + p.Name;
label2.Text = "Product Category: " + p.Category;
label3.Text = "Product Price: " + p.Price;
}
}
Try this!
private void SelectedPreset(object sender, EventArgs e)
{
var p = productList.Where(x => x.Name == (sender as ToolStripMenuItem).Text).Single();
label2.Text = "Product Category: " + (sender as ToolStripMenuItem).Text;
label3.Text = "Product Price: " + p.Price;
}
you must polish up a bit add the proper validation
I am stuck at creating a master detail relationship in C# WPF, between combobox (parent) and listview (child) controls using Linq.
protected class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender{ get; set; }
}
protected static List<Student> students = new List<Student>
{
new Student {FirstName = "Terry", LastName = "Adams", Gender= "M"},
new Student {FirstName = "Terry2", LastName = "Adams", Gender= "M"},
new Student {FirstName = "Karry", LastName = "Adams2", Gender= "F"},
new Student {FirstName = "Karry2", LastName = "Adams4", Gender= "F"},
}
Combobox will be generated by the Gender groubby(), and listview will be updated based on combobox selection. Something like this but in is not working, Thank you
var result = (from cat in students
select new {
FirstName = cat.FirstName ,
LastName = cat.LastName}).Distinct().ToList();
There may be better ways to actually set the data in listview, comboboxes but I'm not too familiar with WPF, the linq's seem right though.
comboBox1.ItemsSource = students.Select(x => x.Gender).Distinct();
private void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
listView1.ItemsSource = students
.Where(x => x.Gender == comboBox1.SelectedItem.ToString()).ToList();
}
Student needs to override ToString()
public override string ToString()
{
return string.Format("{0} {1}", FirstName, LastName);
}
Are you looking for this ?
Sample code :
var result = (from cat in students
select new
{
FirstName = cat.FirstName,
LastName = cat.LastName,
Gender = cat.Gender
}).Distinct().ToList().Where(oc=>oc.Gender == comboBox1.SelectedItem.ToString());
try this solution:
//For Combobox (You can
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var AllGender = (from cat in students select cat.Gender).Distinct();
foreach (var gender in AllGender)
{
comboBox1.Items.Add(gender.ToString());
}
}
//For ListBox
private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string selectedValue = comboBox1.SelectedItem.ToString();
var studentList = from student in students
where student.Gender == selectedValue
select new { Firstname = student.FirstName, LastName = student.LastName };
listBox1.Items.Clear();
foreach (var student in studentList)
{
listBox1.Items.Add(student.Firstname + " " + student.LastName);
}
}
Hope it helps.
I am looking for help, I have two lists that both add data to the same list box and it displays them as a summary, I would like to know how to let the user move an index up or down in the list box.
Items are added here
private void BtnAddpickup_Click(object sender, EventArgs e)
{
/*
* This method creates a new pickup object, allows the user to
* enter details and adds it to the List
*
*/
Pickupform.pickup = new Pickups();
//New Visit- note added to the pickupform object
Pickupform.ShowDialog();
//Show the pickupForm. ShowDialog ensures that the form has the exclusive focus until it is closed.
if (Pickupform.pickup != null)
//if null then the "cancel" button was pressed
{
Pickups newpic = Pickupform.pickup;
//Get the Pickup object from the form
thePickup.addPickups(newpic);
//Add the visit to the list
}
updateList();
//Update the list object to reflect the Pickups in the list
}
and this
public Pickups getPickups(int index)
{
//Return the pickup object at the <index> place in the list
int count = 0;
foreach (Pickups pic in pickups)
{
//Go through all the pickup objects
if (index == count)
//If we're at the correct point in the list...
return pic;
//exit this method and return the current visit
count++;
//Keep counting
}
return null;
//Return null if an index was entered that could not be found
}
This is the same for my other class, So any help would be appreciated
You can try something like this. The following code assumes a Windows form containing a ListBox named mainListBox, a button named upButton, and a button named downButton.
public partial class Form1 : Form
{
private class Person
{
public string LastName { get; set; }
public string FirstName { get; set; }
public override string ToString()
{
return string.Format("{0}, {1}", LastName, FirstName);
}
}
public Form1()
{
this.InitializeComponent();
this.mainListBox.SelectionMode = SelectionMode.One;
this.PopulateListBox();
}
private void PopulateListBox()
{
this.mainListBox.Items.Add(new Person() { FirstName = "Joe", LastName = "Smith" });
this.mainListBox.Items.Add(new Person() { FirstName = "Sally", LastName = "Jones" });
this.mainListBox.Items.Add(new Person() { FirstName = "Billy", LastName = "Anderson" });
}
private void upButton_Click(object sender, EventArgs e)
{
if (this.mainListBox.SelectedIndex > 0)
{
int selectedIndex = this.mainListBox.SelectedIndex;
object selectedItem = this.mainListBox.SelectedItem;
this.mainListBox.Items.RemoveAt(selectedIndex);
this.mainListBox.Items.Insert(selectedIndex - 1, selectedItem);
this.mainListBox.SelectedIndex = selectedIndex - 1;
}
}
private void downButton_Click(object sender, EventArgs e)
{
if (this.mainListBox.SelectedIndex > -1 &&
this.mainListBox.SelectedIndex < this.mainListBox.Items.Count - 1)
{
int selectedIndex = this.mainListBox.SelectedIndex;
object selectedItem = this.mainListBox.SelectedItem;
this.mainListBox.Items.RemoveAt(selectedIndex);
this.mainListBox.Items.Insert(selectedIndex + 1, selectedItem);
this.mainListBox.SelectedIndex = selectedIndex + 1;
}
}
}
This will only work if you are adding items to the ListBox using the ObjectCollection.Add method. If you are data binding, you can update the actual data source and use the ListBox's BindingContext to refresh.
private List<Person> people = new List<Person>();
private void PopulateListBox()
{
this.people.Add(new Person() { FirstName = "Joe", LastName = "Smith" });
this.people.Add(new Person() { FirstName = "Sally", LastName = "Jones" });
this.people.Add(new Person() { FirstName = "Billy", LastName = "Anderson" });
this.mainListBox.DataSource = people;
}
private void upButton_Click(object sender, EventArgs e)
{
if (this.mainListBox.SelectedIndex > 0)
{
int selectedIndex = this.mainListBox.SelectedIndex;
Person selectedItem = this.mainListBox.SelectedItem as Person;
this.people.RemoveAt(selectedIndex);
this.people.Insert(selectedIndex - 1, selectedItem);
this.mainListBox.SelectedIndex = selectedIndex - 1;
this.RefreshListSource();
}
}
private void RefreshListSource()
{
CurrencyManager boundList = this.mainListBox.BindingContext[this.people] as CurrencyManager;
boundList.Refresh();
}
There is a gridView with Items to buy.
Group
- Checkbox|Item Description
And there is a maximum of items that can be bought on each group.
I want to change the appearance of all not selected rows, when the max is reached (per group).
example:
Select 1 item from each group
Group 1
[ ] Item 1
[ ] Item 2
Group 2
[ ] Item 3
[ ] Item 4
[ ] Item 5
After selection
Group 1
[x] Item 1
[ ] Item 2
Group 2
[ ] Item 3
[x] Item 4
[ ] Item 5
After the max amount of items on each group is checked, I want to alter the appearance of the rest of the items.
I have a group summary for the first column. My problem is that I don't know how to trigger the appearance change of all cells. Is it correct to count selected items on each cell-leave event or is there a better way to accomplish this?
I created Devexpress template with GridControl.
Person class was created for me.
I changed it a little for this example.
public class Person {
public Person(string firstName, string secondName) {
this.FirstName = firstName;
this.SecondName = secondName;
this.Comments = String.Empty;
}
public Person(string firstName, string secondName, string comments)
: this(firstName, secondName) {
this.Comments = comments;
}
public bool Selected
{
get;
set;
}
public bool Blocked
{
get;
set;
}
public string FirstName
{
get;
set;
}
public string SecondName
{
get;
set;
}
public string Comments
{
get;
set;
}
}
My grid looks like this:
And I achived Your functionality with code:
public partial class Form1 : XtraForm
{
int max = 2;
public Form1()
{
InitializeComponent();
InitGrid();
}
List<Person> gridDataList = new List<Person>();
void InitGrid()
{
gridDataList.Add(new Person("John", "Smith"));
gridDataList.Add(new Person("Gabriel", "Smith"));
gridDataList.Add(new Person("Ashley", "Smith", "some comment"));
gridDataList.Add(new Person("Adrian", "Smith", "some comment"));
gridDataList.Add(new Person("Gabriella", "Smith", "some comment"));
gridDataList.Add(new Person("John", "Forester"));
gridDataList.Add(new Person("Gabriel", "Forester"));
gridDataList.Add(new Person("Ashley", "Forester", "some comment"));
gridDataList.Add(new Person("Adrian", "Forester", "some comment"));
gridDataList.Add(new Person("Gabriella", "Forester", "some comment"));
bindingSource1.DataSource = gridDataList;
}
private void gridView1_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
{
int parentHandle = gridView1.GetParentRowHandle(e.RowHandle);
int count = gridView1.GetChildRowCount(parentHandle);
int childHandle = -1;
int nCount = 0;
for (int i = 0; i < count; i++)
{
childHandle = gridView1.GetChildRowHandle(parentHandle, i);
Person p = gridView1.GetRow(childHandle) as Person;
if (p != null)
{
p.Blocked = false;
if (p.Selected)
{
nCount++;
}
}
}
if (nCount == max)
{
for (int i = 0; i < count; i++)
{
childHandle = gridView1.GetChildRowHandle(parentHandle, i);
Person p = gridView1.GetRow(childHandle) as Person;
if (p != null && !p.Selected)
{
p.Blocked = true;
}
}
}
// to redraw grid
gridView1.RefreshData();
}
private void richedSelected_EditValueChanged(object sender, EventArgs e)
{
gridView1.PostEditor();
}
private void gridView1_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e)
{
Person p = gridView1.GetRow(e.RowHandle) as Person;
if (p != null && p.Blocked)
{
e.Appearance.ForeColor = Color.White;
}
}
private void richedSelected_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e)
{
Person p = gridView1.GetRow(gridView1.FocusedRowHandle) as Person;
if (p != null && p.Blocked)
{
e.Cancel = true;
}
}
}
This is of course simplified implementation. Just to get You on the right track.
Elements from designer:
private DevExpress.XtraGrid.GridControl gridControl;
private DevExpress.XtraGrid.Views.Grid.GridView gridView1;
private System.Windows.Forms.BindingSource bindingSource1;
private DevExpress.XtraGrid.Columns.GridColumn colFirstName;
private DevExpress.XtraGrid.Columns.GridColumn colSecondName;
private DevExpress.XtraGrid.Columns.GridColumn colComments;
private DevExpress.XtraGrid.Columns.GridColumn colSelected;
private DevExpress.XtraEditors.Repository.RepositoryItemCheckEdit richedSelected;
If You find any better solution please let me know.
Here is an example for what I needed link