【问题标题】:Copying ListView to ListView - C# .NET 2.0将 ListView 复制到 ListView - C# .NET 2.0
【发布时间】:2012-04-22 17:32:39
【问题描述】:

我正在尝试从另一个线程访问 ListView 对象。我这样做的方式是为新线程创建一个临时 ListView,然后在填充新列表时每秒将这个临时 ListView 复制回原始列表。

我在复制 ListView 对象时遇到了困难。我环顾四周,找到了复制项目的方法,但我也需要列和结构也相同。

如果我只是这样做:

ListView lv_temp = lv_original

然后它通过引用复制它,我会得到更多的线程访问错误。

那么如何按值进行完整的克隆呢?

【问题讨论】:

  • 别这样。仅在线程中创建数据。填充它,比如说,一个 List。仅在 UI 线程上填充 ListView。 BackgroundWorker 让它变得简单。
  • 是的,@Hans 说的。必须使用适当的数据源。
  • 这就是我所做的。我只想复制整个 ListView,因为结构已经存在。我刚刚创建了一个具有相同列的新结构,然后将其逐行复制到真实的结构中。

标签: c# .net forms


【解决方案1】:

你要做的是深拷贝列表,所以你可以使用这个扩展:

/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// 
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>

public static class ObjectCopier
{
    /// <summary>
    /// Perform a deep Copy of the object.
    /// </summary>
    /// <typeparam name="T">The type of object being copied.</typeparam>
    /// <param name="source">The object instance to copy.</param>
    /// <returns>The copied object.</returns>
    public static T Clone<T>(T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", "source");
        }

        // Don't serialize a null object, simply return the default for that object
        if (Object.ReferenceEquals(source, null))
        {
            return default(T);
        }

        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream)
        {
            formatter.Serialize(stream, source);
            stream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(stream);
        }
    }
}    

现在,我可以问一下您为什么要这样做,为什么不将列表传递给另一个线程,仅此而已(假设您要再次修改它)。如果它是一个 UI 控件(我看到的可能是这样),您可以使用背景 ItemsSource(来自另一个线程),然后使用 Dispatcher 将其用作 UI 上的源。如果这是您想要的,请告诉我以提供更多详细信息。

【讨论】:

  • 很好的解决方案 - 但是我会先在这里尝试源方法。这种方式需要在我的参考书目中添加另一个来源。
  • 当然,这就是我在第二段中提到的解决方案(但不要解释)。祝你好运:)
  • 我可能是错的,但我认为这与 OP 实际上 试图实现的目标相去甚远 - IMO,问题是 “如何更新我的数据更新时没有跨线程异常时的列表视图"
  • @IAbstract 当然,我理解,但是问题不同。我尝试解决给定的问题。
【解决方案2】:

您需要提供一个对象作为数据源。当您的数据源更新时,UI 控件也会更新。否则,如果遇到线程问题,请使用 SynchronizationContext.Current 并分配给 sync 字段成员,然后:

  // since I believe you don't have lambdas in .net 2.0 I'll try to write this out proper
  // although it is untested, but I hope you get the idea
  sync.Send(new SendOrPostCallback(SendCallBack), stateObject);

  void SendCallBack(object state) {
     // perform UI tasks here
  }

SynchronizationContext 是 .net 2.0 中的新功能

...再次,这是未经测试的,但如果我必须要从这里开始。顺便说一句,在 .net 3.0(?) 中,我们写道:

  sync.Send((state) => {
     // perform UI tasks here
  }, stateObject);

更新
找到答案How do you bind ...。所以不存在我最初假设的 DataSource 属性。

【讨论】:

  • 看起来很整洁。我会看看它是否有效。不过,它必须可以使用我的 Quicksort 功能进行排序 - 只要它是 IComparable,我应该没问题。否则,我需要像 ListView 对象一样制作一个比较器。
  • 您应该为您的列表视图创建一个数据源。然后,您可以实现任何您希望的行为。
  • 这个答案或其他答案都没有用。尝试将数据源强制放入 ListView 是不值得的,所以我放弃并逐列复制,逐行复制。
  • 那么,关于您正在尝试做的事情,我们缺少一些东西。
  • 什么都没有,只是这样做太粗略了。问题仍然相同,但我真正需要在 ListViews 之间复制的只是列和项目行:其他一切都无关紧要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
  • 2011-03-24
  • 1970-01-01
  • 2011-09-24
  • 1970-01-01
  • 2013-12-22
相关资源
最近更新 更多