Click here to Skip to main content
15,881,173 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
first of all please do not confuse with my question title. It is a single seleteditem on Multiple datagrid ( not multipleselecteditems on a single datagrid).

I have multiple datagrids ( say three ), each datagrid from the lowest depends for its data from the selecteditem from the above datagrid. I have asked questions on selecteditem on datagrid by populating the data from a sqlserver few weeks ago, and i managed to solve this issue with some answers.

WPF SelectedItem binding between two datagrids[^]

is it possible to use the same selecteditem of a datagrid on multiple datagrid's ? for example,in the previous problem it was only 1:1 datagrid, will it be possible to implement the same concept like there are three datagrids,

VB
one - Person

two- PersonDetails

Three- PersonStatus


1. first the Person datagrid loads by default (from the database)

2. Persondetails table data is displayed when a selecteditem is clicked on the Person datagrid(achieved this already)

3. PersonStatus table data should be displayed when the selecteditem is clicked on Persondetails( is this possible, it is like a tree one after the other)

This is how it will look like, I have achieved the selecteditem between the first two datagrid's

http://postimage.org/image/4cpoi2e07/[^]

My MainViewModel.cs

C#
//Datacontext
        public MainViewModel()
        {
            this.Persons = Person.GetPersons();
        }
     
        // for Person Datagrid
        private ObservableCollection<Person> personValues;
        public ObservableCollection<Person> Persons
        {
            get { return personValues; }
            set { this.SetProperty<ObservableCollection<Person>>(ref this.personValues, value); }
        }

       //for the PersonDetails datagrid
        public ObservableCollection<PersonDetails> Details
        {
            get
            {
                if (this.Selectedperson == null)
                {
                    return null;
                }
                return this.LoadDetails(this.Selectedperson.PersonID);
            }

        }
        // method to load the persondetails data
        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;
        }

        // SelectedPerson Property
        private Person selectedPersonValue;
        public Person Selectedperson
        {
            get { return selectedPersonValue; }
            set
            {
                this.SetProperty<Person>(ref this.selectedPersonValue, value);
                this.RaiseNotification("Details");
            }
        }

        //for the PersonStatus datagrid
        public ObservableCollection<PersonStatus> Statuses
        {
            get 
            {
                if (this.SelectedDetail == null)
                {
                    return null;
                }
                return this.LoadStatus(this.SelectedDetail.DetailID);
            }
        }

        // method for loading the Status details
        private ObservableCollection<PersonStatus> LoadStatus(int detailID)
        {
            ObservableCollection<PersonStatus> statuss = new ObservableCollection<PersonStatus>();
            foreach (PersonStatus status in PersonStatus.GetStatus().Where(item => item.DetailID == detailID))
            {
                statuss.Add(status);
            }
            return statuss;
        }

        // SelectedDetail Property
        private PersonStatus selectedDetail;
        public PersonStatus SelectedDetail
        {
            get { return selectedDetail; }
            set
            {
                this.SetProperty<PersonStatus>(ref this.selectedDetail, value);
                this.RaiseNotification("Statuses");
            }
        }


XAML

XML
<Grid>
       <DataGrid Margin="100,12,116,219" ItemsSource="{Binding Persons}" SelectedItem="{Binding Selectedperson, Mode=TwoWay}"  />
       <DataGrid Margin="100,110,116,121" ItemsSource="{Binding Details}" SelectedItem="{Binding SelectedDetail,Mode=TwoWay}" />
       <DataGrid ItemsSource="{Binding Statuses}" Margin="100,210,116,21" />
   </Grid>



when I try this code i get this following error :
http://s10.postimage.org/bxk7etjjd/SOerror.png[^]

kindly help to proceed further. Thanks
Posted
Comments
Jason Gleim 26-Feb-13 9:55am    
Set a breakpoint at the top of that method and step through it using F11. Make sure that it isn't being called a bunch of times. It could be that when you populate the first grid, SelectedItem is being set to each row as it is being inserted into the grid. (You could test this by putting a breakpoint in the SelectedItem property setter and running the app. If it breaks there when the first grid is being filled in, then that is the problem.) This could be causing GetDetails to be called for every row in the top grid (recursively too I believe). That would definitely cause a stack overflow.

If this is the case, you may need to add some logic to inhibit getting the details while a grid is being updated. Since you have methods to get the data for a grid, set a flag at the beginning and use that in the lower grid GetDetails methods to skip over getting the details if the flag is set. Really, you don't want to get the details until a user selects a row anyway so it won't hurt doing this.
BuBa1947 26-Feb-13 10:37am    
I have already tried using breakpoint at top of the method. everything works fine until I select the item in the second datagrid, there it takes a pause for 3-4 secs and an exception occurs at da.Fill(row) :(

http://s23.postimage.org/shhz62bjf/Soerror2.png

I suspect here,

do I have to create a separate property again for <PersonDetails> as

private ObservableCollection<PersonDetails> personDetails;
public ObservableCollection<PersonDetails> Details
{
get { return personDetails; }
set { this.SetProperty<observablecollection&lt;persondetails>>(ref this.personDetails, value); }
}

but this creates duplicate for Details.

did u have a look at my MainViewModel. is everything ok there Mr.Jason. what do u think?
Jason Gleim 26-Feb-13 14:18pm    
I'm curious why you would get a stack overflow filling the data adapter. Do you have a huge number of rows in the database? Are you sure da.Fill isn't being called recursively?

You might try using a SqlDataReader rather than the SqlDataAdapter since it looks like you are only reading the data from the DB and not updating anything. The DataReader is more efficient in these situations. Although I don't know if that will fix it or not. I'm not a data guy so that is a bit out of my expertise.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900