Search code examples
c#wpfdatagrid

DataGrid binded to ObservableCollection<ParentType> add line of Children type with canUserAddRows="true"


I'm trying to refactor some classes that have a lot of code duplicated and are hard to maintain. They all are user controls with similar behaviors and always displaying a different type of object in an ObservableCollection.

For that, I created two new classes to refatcor functions, which I can sum up to :

public class WorkItem : INotifyPropertyChanged
{
    protected string _typeModif = "";
    public string typeModif
    {
        get { return _typeModif; }
        set { _typeModif = value; }
    }

    public WorkItem()
    {
        typeModif = "";
    }

    // Property changed stuff
}

and

public abstract class ChildUserControl_MasterData
{
    public ObservableCollection<WorkItem> LstMasterData_AFF = new ObservableCollection<WorkItem>();
}

I use it this way in the children classes :

public partial class MD_Article : ChildUserControl_MasterData
{
    DataSet ds = clsInterfaceBD.getLstArticle();
    if (ds.Tables.Count > 0)
    {
        foreach (DataRow dr in ds.Tables[0].Rows)
        {
            LstMasterData_AFF.Add(new Article(dr));
        }
    }
}
public class Article : WorkItem
{
    public Article()
    {
        ...
    }
}
<DataGrid CanUserAddRows="True"
          ItemsSource="{Binding LstMasterData_AFF, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

Everything is displayed correctly, but my problem occurs when I want to add a new line. I have to keep using the old method to insert lines that works with CanUserAddRows. The object is created with the type WorkItem, which has to be the default behavior. But it creates several problems :

  • I can't make WorkItem and abstract class, which it was supposed to be at the beginning, because CanUserAddRows wants to create an instance of the class.
  • When I want to make operations on the Collection, it is of the type WorkItem and not Article, which I can't process.

Is there a way I'm missing to make the new line of the correct type using AddNewRows ?

Don't hesitate to tell me if my description is not clear.


Solution

  • WorkItem cannot be abstract. And if you want Article objects to be created, you should change the type of the source collection from ObservableCollection<WorkItem> to ObservableCollection<Article>.

    For the CanUserAddRows property to work as expected, the type T of the IEnumerable<T> that is set as the ItemsSource of the DataGrid must have a public default constructor. This is a requirement.

    You can set values for the new item of type T by handling the InitializingNewItem event and setting the values programmatically.

    If you want to customize the creation of the objects any further than this, you should probably set CanUserAddRows to false and implement your own custom solution of adding items to the source collection.