Retrieving items from a List<t>

J

John

Does anyone know how to retrieve the items from a List<T>
once you put the items in the list?

I have the following code

Lasse,

Actually that is what I was going to do until the other option
were laid out on the table for me. I am trying to use list right
now. I have run into a few issues so far.

//This is my class:
public class Person
{
public string Name;
public string Address;
public string Phone;
public Person(string name, string address, string phone)
{
this.Name = name;
this.Address = address;
this.Phone = phone;
}
}

// apply info to the list and assign it to the nodes tag property of
treenode
private void button4_Click(object sender, EventArgs e)
{
if (treeView1.SelectedNode == null)
return;

List<Person> people = new List<Person>();
people.Add(new Person(textBox1.Text, textBox2.Text,
textBox3.Text));
treeView1.SelectedNode.Tag = people;
}

// How do I get the information back from the tag? I want to display it in
a listview.
// this doesn't work.

private void treeView1_Click(object sender, EventArgs e)
{
listView1.BeginUpdate();
listView1.Items.Clear();
List<Person> people = new List<Person>();
people.ForEach(delegate(Person p)
{
ListViewItem item1 = new ListViewItem(p.name, 0);
item1.SubItems.Add(p.address);
item1.SubItems.Add(p.phone);
listView1.Items.Add(item1);
});
listView1.EndUpdate();
}

All I need is an example of storing and retrieving the data from different
parts
of the program.

Thank you
 
M

Mattias Sjögren

// How do I get the information back from the tag? I want to display it in
a listview.
// this doesn't work.

private void treeView1_Click(object sender, EventArgs e)
{
listView1.BeginUpdate();
listView1.Items.Clear();
List<Person> people = new List<Person>();

I think what you want is

List<Person> people = treeView1.SelectedNode.Tag as List<Person>;


Mattias
 
P

Peter Duniho

Does anyone know how to retrieve the items from a List<T>
once you put the items in the list?

Yes. Just use the indexer on the class (e.g. "list[10]") or enumerate the
elements (e.g. "foreach (Person person in list)"), or any of the other
methods defined on the List<T> class that retrieve items.

But based on the code you posted, that doesn't really seem to be your
actual question.
[...]
// How do I get the information back from the tag? I want to display it
in a listview.

You need to cast the Tag property back to List said:
// this doesn't work.

private void treeView1_Click(object sender, EventArgs e)
{
listView1.BeginUpdate();
listView1.Items.Clear();
List<Person> people = new List<Person>();

In the line above, you are creating a new List<Person>. That's not going
to help you get things from the List said:
people.ForEach(delegate(Person p)
{
ListViewItem item1 = new ListViewItem(p.name, 0);
item1.SubItems.Add(p.address);
item1.SubItems.Add(p.phone);
listView1.Items.Add(item1);
});

While I love anonymous methods as much as the next guy, if not more, I'm
not really sure what value is added here by using one.

I think what you really want is code that looks something like this:

foreach (Person person in (List<Person>)treeView1.SelectedNode.Tag)
{
ListViewItem item1 = new ListViewItem(person.name, 0);

item1.SubItems.Add(person.address);
item1.SubItems.Add(person.phone);
listView1.Items.Add(item1);
}
All I need is an example of storing and retrieving the data from
different
parts of the program.

Using the Tag property is one way to do this, as demonstrated by your
example and the changes above to make it work. However, I think it's
worth keeping in mind that it's not always the best way. One thing I
notice about this is that your code is completely dependent on the order
in which the user does things. They first have to initialize a hidden
state in the TreeView instance, which is then read later to initialize the
ListView instance.

IMHO, I think a better paradigm would be for the controls to always be
linked in the first place so that changes in the source data and in the
selected node of the TreeView are automatically reflected in the
ListView. I realize this doesn't have anything to do with your original
question, but I think it's worth mentioning and worth your time to
consider.

Pete
 
P

Peter Duniho

I think what you want is

List<Person> people = treeView1.SelectedNode.Tag as List<Person>;

Not unless he's going to check to see if "people" winds up being null, and
handling that gracefully.

Otherwise, a straight cast is more appropriate.

Pete
 
J

John

Pete,

This sounds like a good idea, but I am not really following code wise on
what you
are saying. Link the treenode to the listview, I thought that is what I was
doing by
storing the information for the listview into each treenode.

Can you elaborate a bit more, perhaps a simple example.

I thought I had the right idea the other day by using an array, then it was
pointed
out to me to use the List<T> which is a lot better since I can add, delete
and modify
the items in the list.

Your idea I would like to try too since it sounds really good, but I am not
following so far
on how to do that.


John


IMHO, I think a better paradigm would be for the controls to always be
linked in the first place so that changes in the source data and in the
selected node of the TreeView are automatically reflected in the
ListView. I realize this doesn't have anything to do with your original
question, but I think it's worth mentioning and worth your time to
consider.

Pete
 
P

Peter Duniho

Pete,

This sounds like a good idea, but I am not really following code wise on
what you
are saying. Link the treenode to the listview, I thought that is what I
was doing by
storing the information for the listview into each treenode.

You are, sort of. It's how integrated the UI is with changes to the
data. Specifically, when you add a new element to the List<Person>,
there's no code that updates the ListView to represent that change. Also,
you only update the ListView in response to actual Click events in the
TreeView, but there are other ways for the selected node to change.

It's my opinion that it would be better to keep the ListView more tightly
connected to the state of the TreeView than that.

You could take it one step further and separate your data from the GUI
even more, using a BindingList<Person> instead, which provides events to
detect changes to the list. Then the ListView could just be bound to the
current BindingList<Person> (which would change according to the TreeView
selection), and as that list changes contents, or a new list is assigned
as the current list for the ListView, the ListView would update
automatically.

One last thing: the example of code I posted was for the updating of the
ListView, of course. You would also need to do the symmetric thing in the
"button4_Click" method. Instead of always instantiating a List<Person>
there, you need to get the current value of the treeView1.SelectedNode.Tag
property, and if it's null, create a new List<Person> to use and assign
that to the Tag property, but otherwise use the instance that's already
set there.

Or you could just always create the List<Person> when you create the node
itself. But either way, you need to make sure there's just the one
List<Person> associated with the node all the time, and that rather than
overwriting a previous List<Person> instance for the node, you just use
whatever's already there.

Pete
 
J

John

Hi Pete,
You could take it one step further and separate your data from the GUI
even more, using a BindingList<Person> instead, which provides events to
detect changes to the list. Then the ListView could just be bound to the
current BindingList<Person> (which would change according to the TreeView

Is this difficult to do? I understand what you are saying, but I have never
had
to do anything like that before. So that leaves me as how do you do it?
I just need a head start.
selection), and as that list changes contents, or a new list is assigned
as the current list for the ListView, the ListView would update
automatically.

I am looking forward in seeing how this is actually done. If you can
provide
an example, make it simple so I can follow what's going on, it will be
greatly
appreciated and I will be on my way with this.

Thank you Pete.


John
 
P

Peter Duniho

Hi Pete,


Is this difficult to do? I understand what you are saying, but I have
never had
to do anything like that before. So that leaves me as how do you do it?
I just need a head start.

Well, maybe it'd be better to start with the more basic suggestion I
offered. Especially since I'm doing a little hand-waving above. I know
that binding should be possible, but I don't actually use binding myself
that often and I'm not entirely clear on how binding with ListView would
work (with simpler controls, in which there's a simple display of a list
of text items, it's very straight-forward...for example, in ListBox, just
set the DataSource property, and it does the right thing, assuming your
class overrides ToString() in a useful way).

Even using binding, you'll have to react to changes in the selection,
which is demonstrated in this example illustrating the simpler
suggestion. The main difference between this example and the code you
posted is that the ListView always stays current with whatever is going on
in the TreeView.

Marc Gravell has helped me out with binding questions in the past, so
maybe he'll have some insight as to a specific technique that would hook
up a BindingList<Person> with a ListView. In the meantime, here's an
example (see below) of doing a similar thing, but with a little more code
(i.e. it's more explicit, because it's not using binding).

Pete

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace TestBindingListView
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

public class Form1 : Form
{
private struct ItemData
{
public readonly string Item;
public readonly string Details;

public ItemData(string item, string details)
{
Item = item;
Details = details;
}
}

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
TreeNodeCollection nodes = treeView1.SelectedNode != null ?
treeView1.SelectedNode.Nodes : treeView1.Nodes;

nodes.Add(textBox1.Text);
}

private void button2_Click(object sender, EventArgs e)
{
TreeNode node = treeView1.SelectedNode;

if (node != null)
{
List<ItemData> rgid = (List<ItemData>)node.Tag;

if (rgid == null)
{
rgid = new List<ItemData>();
node.Tag = rgid;
}

rgid.Add(new ItemData(node.Text, textBox2.Text));
_UpdateListView(rgid);
}
}

private void _UpdateListView(List<ItemData> rgid)
{
listView1.Items.Clear();

if (rgid != null)
{
foreach (ItemData id in rgid)
{
ListViewItem lvi = new ListViewItem(id.Item);

lvi.SubItems.Add(id.Details);
listView1.Items.Add(lvi);
}
}
}

private void treeView1_AfterSelect(object sender,
TreeViewEventArgs e)
{
TreeNode node = treeView1.SelectedNode;

if (node != null)
{
_UpdateListView((List<ItemData>)node.Tag);
}
else
{
_UpdateListView(null);
}
}

private void treeView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
treeView1.SelectedNode = null;
e.Handled = true;
}
}

/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be
disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.treeView1 = new System.Windows.Forms.TreeView();
this.listView1 = new System.Windows.Forms.ListView();
this.columnHeader1 = new System.Windows.Forms.ColumnHeader();
this.columnHeader2 = new System.Windows.Forms.ColumnHeader();
this.button2 = new System.Windows.Forms.Button();
this.textBox2 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(13, 13);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(96, 23);
this.button1.TabIndex = 0;
this.button1.Text = "New Tree Node";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new
System.EventHandler(this.button1_Click);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(115, 15);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 1;
//
// treeView1
//
this.treeView1.Anchor =
((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top
| System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.treeView1.Location = new System.Drawing.Point(13, 43);
this.treeView1.Name = "treeView1";
this.treeView1.Size = new System.Drawing.Size(292, 257);
this.treeView1.TabIndex = 2;
this.treeView1.AfterSelect += new
System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
this.treeView1.KeyDown += new
System.Windows.Forms.KeyEventHandler(this.treeView1_KeyDown);
//
// listView1
//
this.listView1.Anchor =
((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles..Top
| System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.listView1.Columns.AddRange(new
System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2});
this.listView1.Location = new System.Drawing.Point(311, 43);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(174, 257);
this.listView1.TabIndex = 3;
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.View = System.Windows.Forms.View.Details;
//
// columnHeader1
//
this.columnHeader1.Text = "Item";
//
// columnHeader2
//
this.columnHeader2.Text = "Description";
this.columnHeader2.Width = 108;
//
// button2
//
this.button2.Location = new System.Drawing.Point(311, 13);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(64, 23);
this.button2.TabIndex = 4;
this.button2.Text = "New Item";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new
System.EventHandler(this.button2_Click);
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(381, 15);
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(104, 20);
this.textBox2.TabIndex = 5;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(497, 312);
this.Controls.Add(this.textBox2);
this.Controls.Add(this.button2);
this.Controls.Add(this.listView1);
this.Controls.Add(this.treeView1);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();

}

#endregion

private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.TreeView treeView1;
private System.Windows.Forms.ListView listView1;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.TextBox textBox2;
}
}
 
J

John

Thank you very much Pete. I see in your code you took
into consideration a few different events, that in itself
teaches me a few different things in handling some of
these events.

I do appreciate this example code. I am going to try it out
and hopefully I can advance a bit in doing some more
advanced stuff.


Thanks again

John
 
J

John

Pete,

I just tried the sample you posted and it works great.

Thanks again for your help.


John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top