Chris Hayes
Chris Hayes

Reputation: 4037

How do I make a list that has a primary item

I need a List of items with sharable behavior.

Example:

Person class

has List<PhoneNumber> where only one PhoneNumber is bool IsPrimary same for other items has List<EmailAddress> has List<Address>

Imagine each item (PhoneNumber, EmailAddress, Address) share the same interface ICanBePrimary which contains the requirement of one property bool IsPrimary and when in a List<ICanBePrimary> only one item in the list can have a true value for IsPrimary.

Upvotes: 1

Views: 124

Answers (3)

Arek Bal
Arek Bal

Reputation: 733

Do you use or could use INotifyPropertyChanged in your Person, EmailAddress, and Address classes?

Do you really require IsPrimary property to be part of your classes?

IF YOU DO

Then you could be listening to all PropertyChanged events(which are part of that interface) on your items and intercept changes to IsPrimary, then you would check if it's switching to ON and then switch IsPrimary on all other items to OFF.

Keep in mind that it is the proper way of achieving behavior you asked for. SO YES it is proper answer.

PS. You could also use CollectionView class if you are only interested in "CurrentItem" behavior.

Upvotes: 0

Jord&#227;o
Jord&#227;o

Reputation: 56457

You can create your own specialized collection class that has the notion of its primary item.

Something like this:

public class ListWithPrimary<T> : List<T> {
    public bool HasPrimary { get; private set; }
    private T primary;
    public T Primary
    {
        get
        {
            return primary;
        }
        set
        {
            if (!Contains(value)) throw new Exception();
            primary = value;
        }
    }
    public void AddPrimary(T item)
    { 
        Add(item);
        primary = item;
        HasPrimary = true;
    }
    public void ClearPrimary() {
        primary = default(T);
        HasPrimary = false;
    }
    .... 
}

(Note that the above is still incomplete. You'll have to maintain the invariant that the primary item is always part of the list.)

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

The cleanest approach would be to hide a list behind a class that lets you enumerate over the content, and provides additional methods for identifying the primary item:

class AddressList : List<Address> {
    private int indexOfPrimaryAddress = 0;
    public Address PrimaryAddress {
        get {
            return this[indexOfPrimaryAddress];
        }
        set {
            indexOfPrimaryAddress = this.IndexOf(value);
        }
    }
    // Override more methods to make sure that the index does not become "hanging"
}

An even cleaner implementation would encapsulate the list inside your AddressList class, and expose only the methods that you want exposed:

class AddressList : IList<Address> {
    private int indexOfPrimaryAddress = 0;
    private readonly IList<Address> actualList = new List<Address>();
    // Implement the List<Address> by forwarding calls to actualList
}

Upvotes: 3

Related Questions