I often have the problem, that I need to synchronize two lists in C#. For example, I have a simple array of strings. these strings I want to load into the Items list of a Listview in a very simple way. I also want to update the listview with a minimal exchange of items.
example:
var strings = new List<string>() { "a", "b", "c", "d" };
listview1.Items.Synchronize(strings);
strings.Add("xx");
listview1.Items.Synchronize(strings); // just create a new item for xx
I have here a short extension function, which synchronizes two lists with different types. Lambda extension functions do the conversion. example usage:
listView1.Items.SyncList(strings, lvItem => lvItem.Tag as string, str => new ListViewItem(str) { Tag = str });
the extension function is defined as this:
/// <summary>
/// synchronizes an enumerable with a list with two different types,
/// </summary>
/// <typeparam name="TSource">Type of the elements in the source list</typeparam>
/// <typeparam name="TDestination">Type of the elements in the destination list</typeparam>
/// <param name="source">Source</param>
/// <param name="destination">Destination list</param>
/// <param name="selector">returns the corresponding source object for the destination list item</param>
/// <param name="creator">Creates new object for the destination list from the source. The selection function applied on the new object must return the source object. </param>
public static void SyncList<TSource, TDestination>(this IList destination, IEnumerable<TSource> source, Func<TDestination, TSource> selector, Func<TSource, TDestination> creator)
where TDestination : class
where TSource : class
{
if (source == null)
throw new ArgumentNullException("source");
if (destination == null)
throw new ArgumentNullException("destination");
if (selector == null)
throw new ArgumentNullException("selector");
if (creator == null)
throw new ArgumentNullException("creator");
var syncObject = destination.IsSynchronized ? destination.SyncRoot : new object();
lock (syncObject)
{
var ExistingItems = destination.OfType<TDestination>().Where(d => selector(d) != null).ToDictionary(d => selector(d));
foreach (var s in source)
{
if (!ExistingItems.Remove(s)) // s does not exist yet in the destination list
{
var NewObject = creator(s);
if (selector(NewObject) != s)
throw new ArgumentException("the selector must return the creation object of the new item");
destination.Add(creator(s));
}
}
var RemovedItems = ExistingItems.Values;
if (RemovedItems.Count == destination.Count)
destination.Clear();
else
foreach (var i in RemovedItems)
{
destination.Remove(i);
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.