This is a migrated thread and some comments may be shown as answers.

IsReadOnlyBinding with derived classes in hierarchy

4 Answers 83 Views
TreeListView
This is a migrated thread and some comments may be shown as answers.
Jay
Top achievements
Rank 1
Jay asked on 22 Jun 2011, 05:31 PM
I came across an annoying bug in the RadTreeListView this morning!

If I have a class hierarchy similiar to:
public abstract class Person
{
    public string Name { get; set; }
    public decimal Sales { get; set; }
    public bool IsReadOnly { get; set; }
    public abstract string Type { get; }
    private readonly ObservableCollection<Person> _people = new ObservableCollection<Person>();
    public ObservableCollection<Person> People { get { return _people; } }
}
public class Employee : Person
{
    public Employee() { IsReadOnly = true; }
    public override string Type { get { return "Employee"; } }
}
public class Client : Person
{
    public override string Type { get { return "Client"; } }
}

With Xaml similiar to:
<telerik:RadTreeListView Name="radTreeListView1" AutoGenerateColumns="false" >
            <telerik:RadTreeListView.ChildTableDefinitions>
                <telerik:TreeListViewTableDefinition ItemsSource="{Binding People}" />
            </telerik:RadTreeListView.ChildTableDefinitions>
            <telerik:RadTreeListView.Columns>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Name}" Header="Name" IsReadOnlyBinding="{Binding IsReadOnly}" />
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Type}" Header="Type" IsReadOnlyBinding="{Binding IsReadOnly}" />
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Sales}" Header="Sales" IsReadOnlyBinding="{Binding IsReadOnly}" />
                <telerik:GridViewDataColumn DataMemberBinding="{Binding IsReadOnly}" Header="IsReadOnly" IsReadOnlyBinding="{Binding IsReadOnly}" />
            </telerik:RadTreeListView.Columns>
        </telerik:RadTreeListView>

Using this code, I get an exception when I try to edit Joe, Sam, George, or Frank:
public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
        var list = new ObservableCollection<Person>();
        Employee sam = new Employee() { Name = "Alice" };
        list.Add(sam);
        sam.People.Add(new Client() { Name = "Joe" });
        sam.People.Add(new Client() { Name = "Sam" });
        Employee john = new Employee() { Name = "John" };
        john.People.Add(new Client() { Name = "George" });
        john.People.Add(new Client() { Name = "Frank" });
        list.Add(john);
        //list.Add(new Client() { Name = "Jay" });
        radTreeListView1.ItemsSource = list;
    }
}

However if I use the following code:
public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
        var list = new ObservableCollection<Person>();
        Employee sam = new Employee() { Name = "Alice" };
        list.Add(sam);
        sam.People.Add(new Client() { Name = "Joe" });
        sam.People.Add(new Client() { Name = "Sam" });
        Employee john = new Employee() { Name = "John" };
        john.People.Add(new Client() { Name = "George" });
        john.People.Add(new Client() { Name = "Frank" });
        list.Add(john);
        list.Add(new Client() { Name = "Jay" });
        radTreeListView1.ItemsSource = list;
    }
}

I don't get the exception.

Notice the only difference is I included both derived classes in the root collection in the working case, where as there was only a single derived class in the failing case. 

The exception I am receiving is "Unable to cast object of type 'SilverlightApplication5.Client' to type 'SilverlightApplication5.Employee'."

The stack trace is: 
at Telerik.Windows.Data.FuncExtensions.<>c__DisplayClass1`2.<ToUntypedFunc>b__0(Object item)
at Telerik.Windows.Controls.GridViewBoundColumnBase.EvaluateIsReadOnlyState(Object item)
at Telerik.Windows.Controls.GridViewBoundColumnBase.CanEdit(Object item)
at Telerik.Windows.Controls.GridView.GridViewDataControl.BeginEdit(GridViewCell gridViewCell, RoutedEventArgs editingEventArgs)
at Telerik.Windows.Controls.GridView.GridViewDataControl.OnCellMouseDown(GridViewCell cell, MouseButtonEventArgs args)
at Telerik.Windows.Controls.GridView.GridViewCell.OnMouseLeftButtonDown(MouseButtonEventArgs e)
at System.Windows.Controls.Control.OnMouseLeftButtonDown(Control ctrl, EventArgs e)
at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)

One workaround I thought of was to included the second derived class for binding, then remove the second item right away, similar to:
Client jay = new Client() { Name = "Jay" };
list.Add(jay);
radTreeListView1.ItemsSource = list;
list.Remove(jay);

However that doesn't appear to work...

A second more viable option might be a strategy pattern where there is only  a single class in the grid, but this class delegates to the various derived classes. A "hack" but it should work.

Any thoughts?

In my actual use case there will only be one derived class in the grid's root, then a plethora of derived classes down the hierarchy of the grid...

Thanks
Jay




 

4 Answers, 1 is accepted

Sort by
0
Jay
Top achievements
Rank 1
answered on 22 Jun 2011, 05:51 PM
I should add this is with version 2011.1.419.1040 of the controls.

Thanks
Jay
0
Yordanka
Telerik team
answered on 27 Jun 2011, 03:36 PM
Hi Jay,

We are currently investigating the problem and we will contact you as soon as we have more information.
 
Best wishes,
Yordanka
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Yordanka
Telerik team
answered on 14 Jul 2011, 12:52 PM
Hi Jay,

The problem is already resolved and the fix for it is included in our Q2 2011 official version.
 
Kind regards,
Yordanka
the Telerik team

Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!

0
Carson
Top achievements
Rank 1
answered on 16 Aug 2011, 09:31 PM
public abstract class ViewModel
{
    public string Name{get;set;}
    public ViewType Type {get;set;}
  
}
The Above Class is the my base view model that is being displayed in the grid.

I derive several other VM from this one and Bind a grid to them

public class PersonViewModel:ViewModel
{
  public string State{get;set;}
}
  
public class AddressViewModel:ViewModel
{
  public string Street1{get;set;}
}

ObservableCollection<ViewModel> _items;
  
public ObservableCollection<ViewModel>
{
  get
  {
    return _items;
  }
}

The Grid is then bound to the Items property

<GridView:RadGridView 
              ItemsSource="{Binding Items}" 
              CanUserFreezeColumns="False" 
              ScrollMode="RealTime" 
              IsReadOnly="True" 
              x:Name="AlertGrid" IsFilteringAllowed="False"
              GridLinesVisibility="None" AutoGenerateColumns="False"
              MinHeight="350" MaxHeight="525"
              RowStyle="{StaticResource rowStyle}">
              <GridView:RadGridView.Columns>
                  <GridView:GridViewDataColumn Header="Name" SortingState="Descending" DataMemberBinding="{Binding Name}" Width="150" IsFilterable="False"/>
                  <GridView:GridViewDataColumn Header="ViewType" DataMemberBinding="{Binding Type}" Width="150" IsFilterable="False"/>
                       </GridView:RadGridView.Columns>
          </GridView:RadGridView>

When I first load the ites everything in the collection are just PersonViewModel and they display fine. If I group on a property of the base type i.e. ViewModel.Name It will group just fine. However if while grouped I add a new item to the collection that is an AddressViewModel then I get an exception that looks like

The value "AddressViewModel" is not of type "PersonViewModel" and cannot be used in this generic collection.

If I however ungroup the grid and then add the AddressViewModel to the collection and then regroup, it all works as expected and I don't recieve an error.

Understand that my problem has been paraphrased and these are not the exact object names nor fields that I am using in the application, but hopefully describes my problem well enough.

I am using 2011.2.712.1040 of the Grid Controls\


Edit: Just Relized that I posted in the wrong forum, but the issues seem related. If not I will repost in the grid forum
Tags
TreeListView
Asked by
Jay
Top achievements
Rank 1
Answers by
Jay
Top achievements
Rank 1
Yordanka
Telerik team
Carson
Top achievements
Rank 1
Share this question
or