Cannot edit inherited class of IList<T> but works fine with IList reason?

293 views Asked by At

The title kinda says it all, but let me explain it in more detail with examples.

Lets assume you want to create a CustomList for various reason.

For example:

public CustomList<T> : IList<T>
{
   //all members from IList<T> are implemented and are working
}

Now you have a DataGrid which binds to this list

In Code behind of a XAML (WPF) file:

TestDataGrid.ItemsSource = new CustomList<Person>() { new Person(), new Person() };

Now you would assume the editing works fine since the Person class has no retriction what so ever and the IsReadOnly of the CustomList is set to false.

public class Person
{
    public string Name { get; set }
}

But wait, the WPF DataGrid gives out the error Message: 'EditItem' is not allowed for this view.

Now if I change the implementation of my CustomList to this:

public CustomList<T> : IList
{
   //all members from IList are implemented and are working
}

The editing works, but the behaviour or LINQ and IEnumerable extensions just sucks, because the GetEnumerator returns a non generic version so I am stuck with only objects and would need to cast to my desired class all the time.

Am I seeing something wrong or is there no good solution? I just want to have a editable (in WPF DataGrid) CustomList with Sort Functionality (not OrderBy - Sort in place).

3

There are 3 answers

1
Tim S. On BEST ANSWER

Some parts of the WPF engine look for IList, not IList<T>. Since IList<T> does not implement IList, WPF is only aware that your list is IEnumerable, not IList. You should implement both interfaces. You should use explicit interface implementation to hide implementations that shouldn't be public on your object, e.g.

public class CustomList<T> : IList<T>, IList
{
    // this is the one we want users of this class to use
    public void Add(T value) { ... }
    // IList's implementation; needs to exist, but this way it's hidden,
    // unless you cast to IList
    int IList.Add(object value) { this.Add((T)value); return this.Count - 1; }
    // etc
}
0
odyss-jii On

Implement both interfaces IList<T> and IList, just like List<T> does.

0
Quinton Bernhardt On

To get it to work you probably want your CustomList to implement the other required interfaces, like List<T> does. So change from:

public CustomList<T> : IList<T>
{
   //all members from IList are implemented and are working
}

to

public CustomList<T> : IList<T>, IList, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>
{
   //all members from IList are implemented and are working
}