Problems changing DataSource and using an interface type

3 posts, 0 answers
  1. Jérôme
    Jérôme avatar
    2 posts
    Member since:
    Jan 2014

    Posted 11 Apr 2014 Link to this post

    Hi.

    I'm having problems with RadListView, regarding the change of DataSource.

    First problem : using an Interface type
    Here is what I do : I am using RadListView, in details mode, to list objects, implementing a common interface, let's say IListItem.  As a DataSource, I am using a IListItem[ ].

    Let's say I have an array containing two or more types implementing the interface : TypeA and TypeB.
    Using that array as the datasource will do nicely.

    If I use an array containing only objects of TypeA, the RadListView will create not only columns based on IListItem, but also add columns based on TypeA. Is this a desired behavior? I would expect only to see columns based on IListItem.

    I have been able to work around this with ColumnCreating event, adding :
    switch (e.Column.FieldName)
    {
    ...
     default:
                        e.Column.Visible = false;
    }

    Second problem :

    Assuming the same conditions (interface type IListItem, two types implementing it TypeA and TypeB)

    At first, the DataSource is defined with a large array, containing both TypeA and TypeB. After a search (the search is full text and made on sqlserver, a new array is then constructed with new objects), the datasource is changed this way :
    radListView1.DataSource = array;

    If it occurs that the new array contains only TypeA, I get a System.Reflection.TargetInvocationException. The stack trace shows the last call from Telerik code comes from : Telerik.WinControls.Data.RadListSource`1.GetBoundValue.

    And it looks like the reflection exception is trying to access TypeB directly, instead of using the interface (my exception is in french, but it would probably be object does not match target type). It start in my ColumnCreating method, the event being fired after the datasource update.

    That looks a bit to what is described in this thread :
    http://www.telerik.com/forums/refresh-data-in-radlistview-problem#Hlgoam9vfkaKvqTGSWdttg

    My understanding was that the bug was fixed, but I have been able to work around it this way :
    radListView1.Columns.Clear();
    radListView1.DataSource = null;

    before updating the DataSource. Not clearing the Columns seems to affect the AutoSizeMode defined in ColumnCreating because the columns are all too small after a datasource change. Even with Columns.Clear, the AutoSizeMode is not perfect, but it is still better. One of my columns looks a bit too small, maybe adjusting only  at first time?

    Thanks!
  2. Jérôme
    Jérôme avatar
    2 posts
    Member since:
    Jan 2014

    Posted 11 Apr 2014 in reply to Jérôme Link to this post

    Hi. I think I found a better workaround for the second problem (or solution...)

    The exception was raised in my ColumnCreating handler. The method is basically a switch on the column name that sets the BestFitMod. At the end, I was calling : e.Column.BestFit. That was where the exception was raised. Maybe it was not supposed to be there? Not even sure if BestFit() is related with AutoSizeMode....

    Anyway, I put the BestFit call after the DataSource change instead of ColumnCreating and I have no more TargetInvocationException. I can even remove the call to DataSetNull and Columns.Clear.
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Dess
    Admin
    Dess avatar
    1609 posts

    Posted 16 Apr 2014 Link to this post

    Hello Jérôme,

    Thank you for contacting Telerik Support.

    When you bind a RadListView (DetailsView) to a collection of custom objects, depending on the available properties of the custom objects, such columns are created. However, when you have a collection of a base class or interface and this collection contains elements of different derivative types, only columns for the common properties are created. In all other cases, when the collection is composed of identical objects, columns for the object's properties are created. This is desired behavior. Of course, as you already found out, it is possible to hide the undesired columns.

    Here is a sample code snippet, demonstrating the appropriate approach for changing the data source and adjusting the columns width after the new data source is set:
    public Form1()
    {
        InitializeComponent();
     
        IListItem[] items = new IListItem[10];
     
        for (int i = 0; i < 5; i++)
        {
            items[i] = new ItemA(i,"Title" + i);
        }
        for (int i = 5; i < items.Length; i++)
        {
            items[i] = new ItemB(i,"Description" + i,i * 0.25m);
        }
     
        this.radListView1.DataSource = items;
        this.radListView1.ViewType = Telerik.WinControls.UI.ListViewType.DetailsView;
        DetailListViewElement detailsView = this.radListView1.ListViewElement.ViewElement as DetailListViewElement;
        detailsView.BestFitColumns();
    }
     
    private void radButton1_Click(object sender, EventArgs e)
    {
        IListItem[] items = new IListItem[5];
     
        for (int i = 0; i < 5; i++)
        {
            items[i] = new ItemA(i,"Title" + i);
        }
     
        this.radListView1.DataSource = items;
        DetailListViewElement detailsView = this.radListView1.ListViewElement.ViewElement as DetailListViewElement;
        detailsView.BestFitColumns();
    }
     
    public class ItemA:IListItem
    {
        private int id;
     
        public string TitleA { get; set; }
     
        public ItemA(int idA, string titleA)
        {
            this.id = idA;
            this.TitleA = titleA;
        }
     
        public int Id
        {
            get
            {
                return this.id;
            }
            set
            {
                this.id = value;
            }
        }
    }
     
    public class ItemB:IListItem
    {
        private int id;
     
        public string DescriptionB { get; set; }
     
        public decimal PriceB { get; set; }
     
        public ItemB(int idB, string titleB, decimal priceB)
        {
            this.id = idB;
            this.DescriptionB = titleB;
            this.PriceB = priceB;
        }
     
        public int Id
        {
            get
            {
                return this.id;
            }
            set
            {
                this.id = value;
            }
        }
    }
     
    public interface IListItem
    {
        int Id { get; set; }
    }

    Should you have further questions, I would be glad to help.

    Regards,
    Desislava
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
Back to Top