Mauro Ganswer
Mauro Ganswer

Reputation: 1419

Cannot bind to properties of an object that implements ICollection<T>

To explain my case, let's consider a simple object like this:

public class FixedSeries : Series
{
    int val1, val2;
    public FixedSeries(int val1, int val2) { this.val1 = val1; this.val2 = val2; }
    public int Diff
    {
        get { return val2 - val1; }
        set { val2 = val1 + value; }
    }
}

Then, if in my form I want to bind Diff to a control's value I can do:

BindingSource source;
FixedSeries fixedSeries;
public Form1()
{
    InitializeComponent();

    fixedSeries = new FixedSeries(2, 5);    
    source = new BindingSource();
    source.DataSource = fixedSeries;

    numericUpDown1.DataBindings.Add(new System.Windows.Forms.Binding("Value", source, "Diff", false, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
}

However, if my FixedSeries derive from a more generic Series (see here below) that implements the ICollection<int> interface I get an ArgumentException "Cannot bind to the property or column Diff on the DataSource".

public class FixedSeries : Series
{
    public FixedSeries(int val1, int val2)
    {
        base.Add(val1);
        base.Add(val2);
    }
    public int Diff
    {
        get { return base[1] - base[0]; }
        set { base[1] = base[0] + value; }
    }
}

public interface ISeries : ICollection<int>
{
    int this[int index] { get; }
}
public class Series : ISeries
{
    List<int> vals = new List<int>();
    public int this[int index] 
    { 
        get { return vals[index]; } 
        internal set { vals[index] = value; } 
    }
    public void Add(int item) { vals.Add(item); }
    public void Clear() { vals.Clear(); }
    public bool Contains(int item) { return vals.Contains(item); }
    public void CopyTo(int[] array, int arrayIndex) { vals.CopyTo(array, arrayIndex); }
    public int Count { get { return vals.Count; } }
    public bool IsReadOnly { get { return false; } }
    public bool Remove(int item) { return vals.Remove(item); }
    public IEnumerator<int> GetEnumerator() { return vals.GetEnumerator(); }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return vals.GetEnumerator(); }
}

I guess this has something to do with the ICollection<T> interface and maybe to the fact that .NET expects to bind to items inside. How can I bind to the Diff property in this scenario without removing still the possibilities to bind to items inside the series?

Upvotes: 2

Views: 188

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205629

I guess this has something to do with the ICollection<T> interface and maybe to the fact that .NET expects to bind to items inside.

Correct. More precisely the IEnumerable<T> which ICollection<T> inherits.

How can I bind to the Diff property in this scenario without removing still the possibilities to bind to items inside the series?

Here are some options

(A) Do not use the BindingSource, bind directly to the data source object

numericUpDown1.DataBindings.Add("Value", fixedSeries, "Diff", false, DataSourceUpdateMode.OnPropertyChanged);

(B) Wrap the data source object into a single item array/list and use that as BindingSource.DataSource

source.DataSource = new[] { fixedSeries };

(C) Similar to (B), but use BindingSource.Add method (w/o supplying DataSource property at all)

source.Add(fixedSeries);

Upvotes: 1

Related Questions