Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Duplicate Notifier for a List using ObservableCollection

0.00/5 (No votes)
7 Mar 2012 1  
Duplicate Notifier for a List using ObservableCollection.

Introduction

The normal List class in C# is not capable of providing notifications when an item is added or removed. The .NET Framework provides an ObservableCollection class which is capable of providing these features. In this Article I will demonstrate how ObservableCollection can be used to prevent the addition of a duplicate entry into a List/Collection.

Background 

The overall concept is demonstrated using two simple classes Company and Customer. Company can have many customers but if anyone tries to add a duplicate customer to a Company, that will not be allowed and an exception will be thrown. 

Using the code

The class Customer consists of two properties Id, Name and a constructor to set the values for these properties. 

The class Company consist of properties Id, Name, Customers, and a constructor to set values for these properties.

It also associates the CustomerCollectionChanged method to the CollectionChanged event of the ObservableCollection

/// <summary>
/// Customers collection 
/// </summary>
private ObservableCollection<Customer> customers = null;

/// <summary>
/// Gets the customers of the Company
/// </summary>
public IList<Customer> Customers
{
    get
    {
        return this.customers;
    }

    private set
    {
        this.customers = new ObservableCollection<Customer>(value);
    }
}

/// <summary>
/// Initializes a new instance of the Company class with  ID and Name as Parameter
/// </summary>
/// <param name="id">Company ID.</param>
/// <param name="name">Company Name</param>
public Company(int id, string name)
{
    this.customers = new ObservableCollection<Customer>();
    this.customers.CollectionChanged += this.CustomerCollectionChanged;
    this.Id = id;
    this.Name = name;
}

Whenever a customer is added to the Customers list of the Company, the CustomerCollectionChanged method will be invoked which in turn invokes the ValidateCustomerCollection to prevent the duplicate entry into the Customers list.

/// <summary>
/// Customer collection changed event
/// </summary>
/// <param name="sender">sender is collection</param>
/// <param name="e">event argument of NotifyCollectionChangedEventArgs</param>
private void CustomerCollectionChanged(object sender, 
        System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    ValidateCustomerCollection(e);
}

/// <summary>
/// helper function to validate for duplicate customer.
/// </summary>
/// <param name="eventArg">
/// The event arg.
/// </param>
private  void ValidateCustomerCollection(NotifyCollectionChangedEventArgs eventArg)
{
    
   if (eventArg.Action == NotifyCollectionChangedAction.Add || 
                eventArg.Action == NotifyCollectionChangedAction.Replace)
    {
        for (int i = 0; i < eventArg.NewItems.Count; i++)
        {
            Customer customer = eventArg.NewItems[i] as Customer;

            if (Customers.Where(c => c.Id == customer.Id).Count() > 1)
            {
                customers.Remove(customer);
                throw new ArgumentException("Customer cannot be duplicated.");
            }
        }
    }
}

The Unit Test project contains the positive and negative scenarios for testing the Customers list validation.

[TestMethod]
public void CreateCompany()
{
    int count = 0;
    int[] arr = new int[] { 101, 102, 103 };

    Company company = new Company(201, "Microsoft");
    Customer customer1 = new Customer(101,"Walmart");
    Customer customer2 = new Customer(102, "Tesco");
    Customer customer3 = new Customer(103, "QFC");
    
    //adding unique customers to company     
    company.Customers.Add(customer1);
    company.Customers.Add(customer2);
    company.Customers.Add(customer3);

    foreach (Customer c in company.Customers)
    {
        Assert.AreEqual(arr[count++],c.Id);
    }
}

[TestMethod]
public void CreateCompanyWithException()
{
    try
    {
        Company company = new Company(201, "Microsoft");
        Customer customer1 = new Customer(101, "Walmart");
        
        //adding duplicate customer to company
        company.Customers.Add(customer1);
        company.Customers.Add(customer1);
    }
    catch (ArgumentException ex)
    {
         Assert.AreEqual("Customer cannot be duplicated.", ex.Message);
    }
}

You can download the source code DuplicateNotifierList.zip.

History

  • This is the first version as on 7 March 2012.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here