开发者

C# listview add items

Greetings,

I have a method to capture packets. After capturing I want to add each packet as a row in listview in real time so as soon as I capture packet I want to add it to the list view.

The problem that when I use items.Add() I will get overload argument error. Please advise!!

Here is my code:

private void packetCapturingThreadMethod() {

        Packet packet = null;
       int countOfPacketCaptures = 0;
        while ((packet = device.GetNextPacket()) != null)
            {

            packet = device.GetNextPacket();
            if (packet is TCPPacket)
                {
                TCPPacket tcp = (TCPPacket)packet;
                myPacket tempPacket = new myPacket();

                tempPacket.packetType = "TCP";
                tempPacket.sourceAddress = Convert.ToString(tcp.SourceAddress);
                tempPacket.destinationAddress = Convert.ToString(tcp.DestinationAddress);
                tempPacket.sourcePort = Convert.ToString(tcp.SourcePort);
                tempPacket.destinationPort = Convert.ToString(tcp.DestinationPort);
                tempPacket.packetMessage = Convert.ToString(tcp.Data);
                packetsList.Add(tempPacket);


                string[] row = { packetsList[countOfPacketCaptures].packetType, packetsList[countOfPacketCaptures].sourceAddress, packetsList[countOfPacketCaptures].destinationAddress, packetsList[countOfPacketCaptures].sourcePort, packetsList[countOfPacketCaptures].destinationPort, packetsList[countOfPacketCaptures].packetMessage };
                try {


                    listView1.Items.Add(packetsList[countOfPacketCaptures].packetType, packetsList[countOfPacketCaptures].sourceAddress, packetsList[countOfPacketCaptures].destinationAddress, packetsList[countOfPacketCaptures].sourcePort, packetsList[countOfPacketCaptures].destinationPort, packetsList[countOfPacketCaptures].packetMessage)

                    ; countOfPacketCaptures++;
                lblCapturesLabels.Text = Convert.ToString(countOfPacketCaptures);}
                catch (Exception e) { }

                }
            else if (packet is UDPPacket)
                {

                UDPPacket udp = (UDPPacket)packet;


                myPacket tempPacket = new myPacket();

                tempPacket.packetType = "UDP";
                tempPacket.sourceAddress = Convert.ToString(udp.SourceAddress);
                tempPacket.destinationAddress = Convert.ToString(udp.DestinationAddress);
                tempPacket.sourcePort = Convert.ToString(udp.SourcePort);
                tempPacket.destinationPort = Convert.ToString(udp.DestinationPort);
                tempPacket.packetMessage = Convert.ToString(udp.Data);
                packetsList.Add(tempPacket);
                string[] row = { packetsList[countOfPacketCaptures].packetType, packetsList[countOfPacketCaptures].sourceAddress, packetsList[countOfPacketCaptures].destination开发者_Go百科Address, packetsList[countOfPacketCaptures].sourcePort, packetsList[countOfPacketCaptures].destinationPort, packetsList[countOfPacketCaptures].packetMessage };
                try { dgwPacketInfo.Rows.Add(row);
                countOfPacketCaptures++;
                lblCapturesLabels.Text = Convert.ToString(countOfPacketCaptures);
                }
                catch (Exception e) { }


                }


            }
        }


That's because the Add method does not accept a random sequence of parameters. It can accept parameters only of the types mentioned here:

http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.listviewitemcollection.add.aspx


In addition to what logicnp said, my guess is that you are running your while loop on a separate thread (because otherwise it would block the UI thread).

Once you fix the initial issue, you will need to properly update the UI elements across thread boundaries.

Here's a tutorial that explains the problem and solutions.


This is really just a synthesis of the advice you've been given thus far.

The points that have been given so far are:

  1. Convert your data into a format that ListView can understand.
  2. Separate concerns to make testing and maintenance easier.
  3. Understand and work with the WinForms threading model.

Code follows:

public partial class Form1 : Form
{
  private readonly Device _device;
  private readonly PacketBinder _packetBinder;

  public Form1()
  {
    InitializeComponent();
    _device = Device.GetInstance();
    _packetBinder = PacketBinder.GetInstance(listView1);

    var thread = new Thread(WritePackets);
    thread.IsBackground = true;

    thread.Start();
  }

  private void WritePackets()
  {
    Packet packet = null;
    int countOfPacketCaptures = 0;
    while ((packet = _device.GetNextPacket()) != null)
    {
      packet = _device.GetNextPacket();
      MyPacket tempPacket = null;

      if (packet is TCPPacket)
      {
        TCPPacket tcp = (TCPPacket)packet;
        tempPacket = MyPacket.GetInstance();

        tempPacket.PacketType = "TCP";
        tempPacket.SourceAddress = Convert.ToString(tcp.SourceAddress);
        tempPacket.DestinationAddress =
          Convert.ToString(tcp.DestinationAddress);
        tempPacket.SourcePort = Convert.ToString(tcp.SourcePort);
        tempPacket.DestinationPort = Convert.ToString(tcp.DestinationPort);
        tempPacket.PacketMessage = Convert.ToString(tcp.Data);
      }
      else if (packet is UDPPacket)
      {

        UDPPacket udp = (UDPPacket)packet;


        tempPacket = MyPacket.GetInstance();

        tempPacket.PacketType = "UDP";
        tempPacket.SourceAddress = Convert.ToString(udp.SourceAddress);
        tempPacket.DestinationAddress =
          Convert.ToString(udp.DestinationAddress);
        tempPacket.SourcePort = Convert.ToString(udp.SourcePort);
        tempPacket.DestinationPort = Convert.ToString(udp.DestinationPort);
        tempPacket.PacketMessage = Convert.ToString(udp.Data);
      }

      if (tempPacket != null)
      {
        _packetBinder.AddPacketToView(tempPacket);
      }
    }
  }
}

internal class Device
{
  private Device() { }

  internal static Device GetInstance()
  {
    return new Device();
  }

  internal Packet GetNextPacket()
  {
    var random = new Random();
    var coin = random.Next(2);

    Thread.Sleep(500);

    if (coin == 0)
    {
      return new TCPPacket()
      {
        Data = GetRandomString(random),
        SourceAddress = GetRandomString(random),
        SourcePort = random.Next(),
        DestinationAddress = GetRandomString(random),
        DestinationPort = random.Next()
      };
    }
    else
    {
      return new UDPPacket()
      {
        Data = GetRandomString(random),
        SourceAddress = GetRandomString(random),
        SourcePort = random.Next(),
        DestinationAddress = GetRandomString(random),
        DestinationPort = random.Next()
      };
    }
  }

  private string GetRandomString(Random random)
  {
    var bytes = new byte[16];
    random.NextBytes(bytes);

    return Convert.ToBase64String(bytes);
  }
}

internal class MyPacket
{
  private MyPacket() { }

  internal static MyPacket GetInstance()
  {
    return new MyPacket();
  }

  internal string PacketType { get; set; }
  internal string SourceAddress { get; set; }
  internal string DestinationAddress { get; set; }
  internal string SourcePort { get; set; }
  internal string DestinationPort { get; set; }
  internal string PacketMessage { get; set; }
}

internal class ThreadSafeListViewMutator
{
  private readonly ListView _target;

  private ThreadSafeListViewMutator(ListView target)
  {
    _target = target;
  }

  internal static ThreadSafeListViewMutator GetInstance(ListView target)
  {
    return new ThreadSafeListViewMutator(target);
  }

  internal void AddListViewItem(ListViewItem listItem)
  {
    Action action = () => _target.Items.Add(listItem);
    Delegate asDelegate = action;
    var handle = _target.BeginInvoke(asDelegate);
    _target.EndInvoke(handle);
  }
}

internal class PacketBinder
{
  private readonly ThreadSafeListViewMutator _target;

  private PacketBinder(ListView target)
  {
    _target = ThreadSafeListViewMutator.GetInstance(target);
  }

  internal static PacketBinder GetInstance(ListView target)
  {
    return new PacketBinder(target);
  }

  internal void AddPacketToView(MyPacket tempPacket)
  {
    var listItem = new ListViewItem() { Text = tempPacket.PacketType };

    AddSubItem(listItem, "From", tempPacket.SourceAddress + ":"
      + tempPacket.SourcePort);
    AddSubItem(listItem, "To", tempPacket.DestinationAddress + ":"
      + tempPacket.DestinationPort);
    AddSubItem(listItem, "Message", tempPacket.PacketMessage);

    _target.AddListViewItem(listItem);
  }

  private void AddSubItem(ListViewItem listItem, string attribute, string value)
  {
    listItem.Text = listItem.Text + @"
" + attribute + " = " + value;
  }
}

internal class Packet { }

// Are these really duplicated this way?  Seems crazy...
internal class TCPPacket : Packet
{
  internal string SourceAddress { get; set; }
  internal string DestinationAddress { get; set; }
  internal int SourcePort { get; set; }
  internal int DestinationPort { get; set; }
  internal string Data { get; set; }
}

internal class UDPPacket : Packet
{
  internal string SourceAddress { get; set; }
  internal string DestinationAddress { get; set; }
  internal int SourcePort { get; set; }
  internal int DestinationPort { get; set; }
  internal string Data { get; set; }
}


Also once you get it working, refactor to create a class which inherits from listview and add your own overloaded Add methods which takes your full-blown objects of whatever classes and adds them to the listview appropriately - this will save you some code duplication and make your code a lot cleaner, more readable and maintainable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜