Search code examples
c#interfacebindinglistinherited

BindingList<T> where T is interface that implements other interface


I am stuck with BindingList where T is an interface that extends A interface. WHen i use this bindingList in bindings, only properties from T are visible, while properties from inherited A interface are not. Why is it happening? It looks like a .net bug. This i required for my 2 projects to share some common functionality. Also the binding List has PropertyDescriptor empty, when PropertyChanged event is tunneled from baseImplementation. Attached interfaces and implementations. SetUp method in the end

interface IExtendedInterface : IBaseInterface
{
    string C { get; }
}

interface IBaseInterface : INotifyPropertyChanged
{
    string A { get; }
    string B { get; }
}

public class BaseImplementation : IBaseInterface
{
    public string A
    {
        get { return "Base a"; }
    }

    public string B
    {
        get { return "base b"; }
        protected set
        {
            B = value;
            OnPropertyChanged("B");
        }
    }

    protected void OnPropertyChanged(string p)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(p));
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
}

public class ExtendedImplementation : BaseImplementation, IExtendedInterface
{
    public string C
    {
        get { return "Extended C"; }
    }
}

 private void SetupData()
    {
        BindingList<IExtendedInterface> list = new BindingList<IExtendedInterface>();
        list.Add(new ExtendedImplementation());
        list.Add(new ExtendedImplementation());
        dataGridView1.DataSource = list;
    }

Solution

  • The properties are obtained via (indirectly) TypeDescriptor.GetProperties(typeof(T)), but the behaviour is as expected. Properties from interfaces are never returned, even from class-based models, unless they are on the public API of that type (which for interfaces, means on the immediate type). Class inheritance is different because those members are still on the public API. When an interface : ISomeOtherInterface, that is "implements", not "inherits". To give a simple example of when this could be a problem, consider (fully legal):

    interface IA { int Foo {get;} }
    interface IB { string Foo {get;} }
    interface IC : IA, IB {}
    

    Now; what is IC.Foo ?

    You might be able to hack around this by registering a custom TypeDescriptionProvider for the interface, or using an ITypedList, but both of those are tricky. To be honest, data-binding simply works more easily with classes than interfaces.