【问题标题】:Populating a ListView with objects from a List<>使用 List<> 中的对象填充 ListView
【发布时间】:2009-11-27 22:30:09
【问题描述】:

我目前正在将控制台应用程序转换为 Windows 窗体应用程序。 幸运的是,我最初将应用程序设计为在未来使用 GUI,因此没有太多代码需要更改。

我有一个 UserCollection 类,它本身包含一个用户/成员类型的列表(成员是从用户派生的)。

我想做的是将UserCollection List中的每个项目添加到ListView,这样我就可以看到每个条目并垂直拥有多个条目列表。

我首先尝试自己实现这一点:

        private void UpdatePeopleListings()
    {
        foreach (User person in newCollection)
        {
            listViewPeople.Items.Add(person.ToString());
        }
    }

newCollection 是从主窗口窗体中的 UserCollection 类创建的新对象。

我收到错误:

foreach statement cannot operate on variables of type 'Collection.UserCollection' because 'Collection.UserCollection' does not contain a public definition for 'GetEnumerator'

然后我尝试做一个小的解决方法,所以在我的 UserCollection 中我创建了以下方法:

        public User ReturnUser()
    {
        foreach (User person in _userCollection)
        {
            return person;
        }
        return null;
    }

(_userCollection 是 UserCollection.cs 中用户/成员的列表)

然后像这样使用它:

private void UpdatePeopleListings()
    {
        listViewPeople.Items.Add(newCollection.ReturnUser().ToString());
    }

虽然这确实会使用条目填充 ListView,但它只会填充第一个条目。 如果我要向 newCollection 添加多个用户/成员,那么它只会重复第一个条目。

我将如何正确地使用集合中的所有对象填充 ListView,以及如何防止它仅重复一个对象。

UserColleton.cs

///////////////////////////////////////////////////////////
//  UserCollection.cs
//  Implementation of the Class UserCollection
//  Generated by Enterprise Architect
//  Created on:      22-Oct-2009 22:40:30
///////////////////////////////////////////////////////////

#region Using Statements

using System;

using System.Collections.Generic;

using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

using System.IO;

#endregion

namespace Collection
{
    //Allows the class to be saved
    [Serializable()]

    public class UserCollection
    {
        #region Fields

        //Declares a list of type User (Which also holds derived Member objects)
        private List<User> _userCollection = new List<User>();


        //Holds number of members
        int nMember = 0;
        //Holds number of users
        int nUser = 0;

        #endregion

        #region Add Operations

        /// <summary>
        /// Adds a new user
        /// </summary>
        /// <param name="user"></param>
        public void AddUser(User user)
        {
            //Adds the user given in the operation parameters to the collection
            _userCollection.Add(user);
            nUser++;

            //Sorts the collection using the CompareTo() specified in the User class.
            _userCollection.Sort();

            //Console.WriteLine used for testing purposes
            //Console.WriteLine("added");
        }


        ///<summary>
        ///Adds a new Member
        ///</summary>
        /// <param name="member"></param>
        public void AddMember(Member member)
        {
            //Adds the member given in the operation parameters to the collection
            _userCollection.Add(member);
            nMember++;

            //Sorts the collection using the CompareTo() specified in the User class.
            _userCollection.Sort();

            //Console.WriteLine used for testing purposes
            //Console.WriteLine("added");
        }

        #endregion

        #region Removal Operations

        ///<summary>
        ///Removes a user based on FirstName,LastName and PostCode
        ///</summary> 
        /// <param name="person"></param>
        public void RemoveUser(User person)
        {
            //Only search collection for users if there is data in it
            if (_userCollection.Count > 0)
            {
                //Create a temp list for any matched found
                List<User> tempList = new List<User>();

                foreach (User u in _userCollection)
                {
                    //If the details stored in the collection match the details given in the search
                    if (u.FName == person.FName && u.LName == person.LName && u.PostCode == person.PostCode)
                    {
                        //Add any matches to the temp list
                        tempList.Add(u);
                    }
                    else
                    {
                        throw new ArgumentException("User not found");
                    }
                }

                //Delete any matches 
                foreach (User u in tempList)
                {
                    _userCollection.Remove(u);
                    //Decrement user count
                    nUser--;
                }
            }
            else
            {
                throw new AccessViolationException("No data in collection");
            }
        }

        /// <summary>
        /// Removes a user using Membership number
        /// </summary>
        /// <param name="number"></param>
        public void RemoveMember(int number)
        {
                //Create a temp list of type Member
                Member temp = new Member();

                //Use the temp list to compare types and store all objects of type member
                //found in the collection to it.
                List<User> Mems = _userCollection.FindAll(delegate(User u)
                { return u.GetType() == temp.GetType(); });

                //Delete any matches
                foreach (Member m in Mems)
                {
                    if (m.mNum == number)
                    {
                        _userCollection.Remove(m);
                        //Decrement member count
                        nMember--;
                    }
                    else
                    {
                        throw new ArgumentException("Member not found");
                    }
                }
        }

        #endregion

        #region Search Operations

        ///<summary>
        ///Returns member by Membership number
        /// </summary>
        /// 
        /// <param name="_mNumber"></param>
        public Member FindByMNo(int number)
        {
            //Create a temp list of type Member
            Member temp = new Member();

            //Use the temp list to compare types and store all objects of type member
            //found in the collection to it.
            List<User> Mems = _userCollection.FindAll(delegate(User u)
            { return u.GetType() == temp.GetType(); });

            //Return any matches found
            foreach (Member i in Mems)
            {
                if (i.mNum == number)
                {
                    return i;
                }
            }
            throw new ArgumentException("Member not found");
        }

        ///<summary>
        ///Returns a list of Users matching details given
        ///</summary>
        /// 
        /// <param name="_fName"></param>
        /// <param name="_lName"></param>
        public List<User> FindByName(User person)
        {
            //Create a temp list to store any matches
            List<User> temp = new List<User>();

            //Add matches found to the temp list
            foreach (User u in _userCollection)
            {
                if (u.LName == person.LName)
                {
                    temp.Add(u);
                }
            }

            if (temp.Count > 0)
            {
                //Return the list that holds any matches
                return temp;
            }

            throw new ArgumentException("User not found");
        }

        public User ReturnUser()
        {
            foreach (User person in _userCollection)
            {
                return person;
            }
            return null;
        }

        #endregion

        #region Edit Operations

        ///<summary>
        ///Edits a members membership expiry
        ///</summary>
        /// 
        /// <param name="member"></param>
        public void EditMemStatus(int member, DateTime newDate)
        {
                //Create a temp list of type Member
                Member temp = new Member();

                //Use the temp list to compare types and store all objects of type member
                //found in the collection to it.
                List<User> Mems = _userCollection.FindAll(delegate(User u)
                { return u.GetType() == temp.GetType(); });

                //Search for the member that matches the number given in the parameter
                foreach (Member m in Mems)
                {
                    if (m.mNum == member)
                    {
                        //Replace the match with the new expiry
                        m.mExp = newDate;
                    }
                    else
                    {
                        throw new ArgumentException("Date cannot be changed");
                    }
                }
        }

        #endregion

        #region I/O Operations

        public bool SaveData()
        {
            try
            {
                //Open the stream using the Data.txt file
                using (Stream stream = File.Open("Data.txt", FileMode.Create))
                {
                    //Create a new formatter
                    BinaryFormatter bin = new BinaryFormatter();
                    //Copy data in collection to the file specified earlier
                    bin.Serialize(stream, _userCollection);
                    bin.Serialize(stream, nMember);
                    bin.Serialize(stream, nUser);
                    //Close stream to release any resources used
                    stream.Close();
                }
                return true;
            }
            catch (IOException ex)
            {
                throw new ArgumentException(ex.ToString());
            }
        }

        public bool LoadData()
        {
            //Check if file exsists, otherwise skip
            if (File.Exists("Data.txt"))
            {
                try
                {
                    using (Stream stream = File.Open("Data.txt", FileMode.Open))
                    {
                        BinaryFormatter bin = new BinaryFormatter();

                        //Copy data back into collection fields
                        _userCollection = (List<User>)bin.Deserialize(stream);
                        nMember = (int)bin.Deserialize(stream);
                        nUser = (int)bin.Deserialize(stream);
                        stream.Close();

                        //Sort data to ensure it is ordered correctly after being loaded
                        _userCollection.Sort();
                        return true;

                    }
                }
                catch (IOException ex)
                {
                    throw new ArgumentException(ex.ToString());
                }
            }
            else
            {
                //Console.WriteLine present for testing purposes
                Console.WriteLine("\nLoad failed, Data.txt not found");
                return false;
            }
        }

        #endregion

        #region Properties

        //Gets amount of Members in collection
        public int GetNMember
        {
            get
            {
                return nMember;
            }
        }

        //Gets amount of Users in collectioj
        public int GetNUser
        {
            get
            {
                return nUser;
            }
        }

        #endregion

    }//end UserCollection
}

忽略任何随机的控制台内容,我还没有完成清理。

【问题讨论】:

    标签: .net winforms listview


    【解决方案1】:

    foreach 不起作用,因为您的 UserCollection 类没有实现 IEnumerable 接口。

    ListItems 不是您所期望的,因为您不了解 ListView / ListViewItems 是如何工作的。 ListView 由 ListViewItems 组成,ListViewItem 可以由 SubItems 组成(仅当 ListView 的 viewstyle 设置为 'report' 时才会显示)。

    当您使用您正在使用的方法添加 ListViewItem 时,仅定义 ListViewItem 的“标题”。 这意味着,您将不得不使用 Add 方法的另一个重载;将 ListViewItem 对象作为参数的方法。 然后,您可以这样做:

    ListViewItem item = new ListViewItem();
    item.Text = "bar";
    item.SubItems.Add ("foo");
    item.SubItems.Add ("foo2");
    myListView.Items.Add (item);
    

    关于仅将一项添加到您的列表的问题: - 您只添加一个项目......更具体地说,您正在添加集合本身,而不是为集合中的每个对象创建一个 ListViewItem。

    所以你要做的是:

    • 遍历您的列表(使用 foreach(意味着您必须在集合类上实现 IEnumerable),或使用 for 循环(但您必须确保您可以使用索引器访问集合的内容实例))
    • 为列表中存在的每个对象创建一个 ListViewItem。

    我想知道为什么您首先创建了自定义 UserCollection。我看到您已经实现了一些特定的功能,但是....我认为有更好的解决方案。 尽管如此,您应该为该类实现 IEnumerable 接口、IList 接口等。通过这样做,您的类将成为一个“真正的集合”,然后您可以像使用任何其他集合类一样使用它。 (使用 foreach 进行迭代,或者使用 for 循环等。)

    【讨论】:

    • +1 以上所有内容,还有一件事:考虑使用DataGridView 而不是ListViewDataGridView可以直接绑定collection,不需要创建再同步item。
    • 工作正常,最初有一些问题,并非所有数据都不会显示。我必须手动编写以下属性来显示所有项目和列:listViewPeople.View = View.Details; listViewPeople.FullRowSelect = true; listViewPeople.GridLines = true;此外,有没有一种方法可以让列表不会在我添加新条目时重新填充所有条目。我必须调用 listViewPeople.Items.Clear();在我添加所有项目以确保没有数据重复之前。
    【解决方案2】:

    结合 Frederik Gheysel 的回答,实施 IEnumerator 也是明智之举。这样做时记得覆盖 Equals、GetHashCode 和 ToString。

    【讨论】:

      猜你喜欢
      • 2013-05-07
      • 2014-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-28
      • 1970-01-01
      • 2014-07-23
      • 1970-01-01
      相关资源
      最近更新 更多