.NET Forum / Languages / C# / March 2008
Retrieving items from a List<t>
|
|
Thread rating:  |
John - 11 Mar 2008 22:52 GMT 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
Mattias Sjögren - 11 Mar 2008 23:05 GMT >// How do I get the information back from the tag? I want to display it in >a listview. [quoted text clipped - 5 lines] > 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
 Signature Mattias Sjögren [C# MVP] mattias @ mvps.org http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com Please reply only to the newsgroup.
Peter Duniho - 11 Mar 2008 23:16 GMT > 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
Peter Duniho - 11 Mar 2008 23:12 GMT > 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<Person>.
> // this doesn't work. > [quoted text clipped - 3 lines] > 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<Person> you created earlier.
> people.ForEach(delegate(Person p) > { [quoted text clipped - 3 lines] > 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
John - 12 Mar 2008 00:03 GMT 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
Peter Duniho - 12 Mar 2008 02:57 GMT > Pete, > [quoted text clipped - 3 lines] > 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
John - 12 Mar 2008 03:12 GMT 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
Peter Duniho - 12 Mar 2008 05:28 GMT > Hi Pete, > [quoted text clipped - 9 lines] > 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; } }
John - 12 Mar 2008 13:25 GMT 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
John - 12 Mar 2008 15:30 GMT Pete,
I just tried the sample you posted and it works great.
Thanks again for your help.
John
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|