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

RadGridView: the master-detail case via datatables in WPF

2 Answers 80 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Onotole
Top achievements
Rank 1
Onotole asked on 06 Aug 2013, 12:45 PM
Hello

We trying to implement the master-detail WPF app to learn the capabilities of Telerik RadGridView.

It is a simple application which has RadGridView with the following markup:
<telerik:RadGridView ItemsSource="{Binding Persons}" SelectedItem="{Binding Selectedperson, Mode=TwoWay}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" AutoGenerateColumns="True" telerik:StyleManager.Theme="Windows7">
            <telerik:RadGridView.ChildTableDefinitions>
                <telerik:GridViewTableDefinition>
                </telerik:GridViewTableDefinition>
            </telerik:RadGridView.ChildTableDefinitions>
            <telerik:RadGridView.HierarchyChildTemplate>
                <DataTemplate>
                    <telerik:RadGridView
                            AutoGenerateColumns="True"
                            telerik:StyleManager.Theme="Windows7"
                            ItemsSource="{Binding Details}">
                    </telerik:RadGridView>
                </DataTemplate>
            </telerik:RadGridView.HierarchyChildTemplate>
        </telerik:RadGridView>
Under the hood is view model which is set to DataContext of the main windows where Telerik RadGridView is placed, as follows:
namespace MasterDetailViaDataTables
{
    public partial class MainWindow : Window
    {
 
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainViewModel();
        }

Persons and Details are fields of view model which are ObservableCollection of appropriate instances.
PersonDetails.cs:
namespace MasterDetailViaDataTables
{
    public class PersonDetails : BindableBase
    {
        private int _PersonID;
        public int PersonID
        {
            get { return _PersonID; }
            set { this.SetProperty<int>(ref this._PersonID, value); }
        }
 
        private string address;
        public string Address
        {
            get { return address; }
            set { this.SetProperty<string>(ref this.address, value); }
        }
 
        private string _Description;
        public string Description
        {
            get { return _Description; }
            set { this.SetProperty<string>(ref this._Description, value); }
        }
 
        public static ObservableCollection<PersonDetails> GetDetails()
        {
            ObservableCollection<PersonDetails> details = new ObservableCollection<PersonDetails>();
            try
            {
                DataTable table = new DataTable("persondetail");
                DataColumn PersonID = new DataColumn("PersonID", typeof(System.Int64));
                DataColumn Address = new DataColumn("Address", typeof(System.String));
                DataColumn Description = new DataColumn("Description", typeof(System.String));
                table.Columns.Add(PersonID);
                table.Columns.Add(Address);
                table.Columns.Add(Description);
 
                for (int pID = 1; pID <= 5; pID++)
                {
                    for (int i = 0; i < 2; i++)
                    {
                        DataRow row = table.NewRow();
                        row["PersonID"] = pID;
                        row["Address"] = "Address" + (pID-1).ToString() + " - " + i.ToString();
                        row["Description"] = "Description" + (pID-1).ToString() + " - " + i.ToString();
                        table.Rows.Add(row);
                    }
                }
 
 
                details.Clear();
 
                for (int i = 0; i < table.Rows.Count; ++i)
                    details.Add(new PersonDetails
                    {
                        PersonID = Convert.ToInt32(table.Rows[i][0]),
                        Address = table.Rows[i][1].ToString(),
                        Description = table.Rows[i][2].ToString()
                    });
 
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return details;
        }
    }
Person.cs:
public class Person : BindableBase
{
    private int _PersonID;
    private string _FirstName;
    private string _LastName;
 
    public int PersonID
    {
        get { return _PersonID; }
        set { this.SetProperty<int>(ref this._PersonID, value); }
    }
 
    public string FirstName
    {
        get { return _FirstName; }
        set { this.SetProperty<string>(ref this._FirstName, value); }
    }
 
    public string LastName
    {
        get { return _LastName; }
        set { this.SetProperty<string>(ref this._LastName, value); }
    }
 
    public static ObservableCollection<Person> GetPersons()
    {
        ObservableCollection<Person> persons = new ObservableCollection<Person>();
        try
        {
            DataTable table = new DataTable("person");
            DataColumn id = new DataColumn("PersonID", typeof(System.Int64));
            id.AutoIncrement = true;
            id.AutoIncrementSeed = 1;
            DataColumn FirstName = new DataColumn("FirstName", typeof(System.String));
            DataColumn LastName = new DataColumn("LastName", typeof(System.String));
            table.Columns.Add(id);
            table.Columns.Add(FirstName);
            table.Columns.Add(LastName);
 
            for (int i = 0; i < 5; i++)
            {
                DataRow row = table.NewRow();
                row["FirstName"] = "FirstName" + i.ToString();
                row["LastName"] = "LastName" + i.ToString();
                table.Rows.Add(row);
            }
 
            persons.Clear();
 
            for (int i = 0; i < table.Rows.Count; ++i)
                persons.Add(new Person
                {
                    PersonID = Convert.ToInt32(table.Rows[i][0]),
                    FirstName = table.Rows[i][1].ToString(),
                    LastName = table.Rows[i][2].ToString()
                });
 
 
 
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
 
        }
        return persons;
    }
 
 
}
MainViewModel.cs:
public class MainViewModel : BindableBase, INotifyPropertyChanged
{
    public MainViewModel()
    {
        this.Persons = Person.GetPersons();
    }
 
    private ObservableCollection<Person> personValues;
    public ObservableCollection<Person> Persons
    {
        get { return personValues; }
        set { this.SetProperty<ObservableCollection<Person>>(ref this.personValues, value); }
    }
 
 
    private ObservableCollection<PersonDetails> detailsvalues;
    public ObservableCollection<PersonDetails> Details
    {
        get
        {
            if (this.Selectedperson == null)
            {
                return null;
            }
            return this.LoadDetails(this.Selectedperson.PersonID);
        }
 
    }
 
    private ObservableCollection<PersonDetails> LoadDetails(int personID)
    {
        ObservableCollection<PersonDetails> details = new ObservableCollection<PersonDetails>();
        foreach (PersonDetails detail in PersonDetails.GetDetails().Where(item => item.PersonID == personID))
        {
            details.Add(detail);
        }
        return details;
    }
 
    private Person selectedPersonValue;
    public Person Selectedperson
    {
        get { return selectedPersonValue; }
        set
        {
            this.SetProperty<Person>(ref this.selectedPersonValue, value);
            this.RaiseNotification("Details");
        }
    }
 
}

We can't get working hierarchical RadGridView. When we trying to expand the parent row, we see the following in the Output window:
System.Windows.Data Error: 40 : BindingExpression path error: 'Details' property not found on 'object' ''Person' (HashCode=43402647)'.
BindingExpression:Path=Details; DataItem='Person' (HashCode=43402647); target element is 'RadGridView' (Name=''); target property is 'ItemsSource' (type 'Object')
We can't figure out what is wrong here, can you help us?

2 Answers, 1 is accepted

Sort by
0
Accepted
Rossen Hristov
Telerik team
answered on 06 Aug 2013, 12:54 PM
Hi,

The DataContext of each child grid is the parent data item, i.e. Person. Since Person does not have a Details property your Binding fails. Each Person should have many PersonDetails, hence the Person class should have an IEnumerable<PersonDetail> property which the child grid can bind to.

This is how one-to-many relationships are established.

Regards,
Rossen Hristov
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
0
Onotole
Top achievements
Rank 1
answered on 06 Aug 2013, 12:56 PM
Thanks!
Tags
GridView
Asked by
Onotole
Top achievements
Rank 1
Answers by
Rossen Hristov
Telerik team
Onotole
Top achievements
Rank 1
Share this question
or