Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm relatively new to WPF and I am trying to make a control where I display data from multiple source objects. The source objects are stored in a collection in my view model and each item has a name and a collection of data objects. Each data object has some properties representing it. The data structure looks something like this:

In the view model

ObservableCollection<MySourceObjectType> sourceItems {get; set;}

MySourceObjectType:

SomeType Name {get; set;}
SomeType Number {get; set;}
IList<MyDataObjectType> {get; set;}

MyDataObjectType:

SomeType data1 {get; set;}
SomeType data2 {get; set;}
SomeType data3 {get; set;}

I want my grid to look something like this:

Sample grid layout

In addition to that layout, the control needs to support reordering the column groups that correspond to each source object and all rows need to scroll vertically together as if they were all in the same datagrid. The column and group headers also need to be frozen to the top so that they are visible regardless of the scroll position. The individual columns should not be able to be reordered relative to one another and the column groups must always stay together. The source items can be an arbitrarily sized collection so I can't predefine the groups, but the columns within each group are predefined and won't change.

Currently I have this working by using a ListBox with its ItemSource bound to sourceItems. The item template is a dockpanel with a text box for the super header and a datagrid to display the data for each item. I can reorder them with drag and drop with a bunch of event handlers and I synced the scrolling with event handlers as well. The reordering currently is getting a reference to the source collection and reordering that when the drop happens which violates the mvvm.

I want to know if there is a better, cleaner way to do this other than using a separate DataGrid for each item. I have played around with having auto generated columns for each item and then the cell template would be another DataGrid. I couldn't figure out how to make it work and doesn't seem any better other than the group reordering being taken care of by the DataGrid itself.

My current thought is that I will have to create a custom control for a GroupedDataGrid or whatever and give it the ability to reorder groups, but I'd definitely be interested in an easier way to accomplish the task.

My basic requirements are that it must follow strict MVVM and my main xaml layout can have no code behind. I imagine if the code behind is minimal and purely UI manipulation I can squeak it by, but no code behind is ideal.

Any ideas?

share|improve this question
 
Definitely a good candidate for a custom control. You could probably get away with modifying the header template to get the multi-spanning columns, but the reordering will be tricky and will inevitably end up having too much code in tied up in your window handling that. –  Shoe Sep 20 at 18:53
add comment

1 Answer

This would be a partial answer since providing an implementation would take some time , how ever since this is of interest to me i'll attempt to supply you with an implementation later on .

What you need to do would involve using grouping ,

  1. Add some common property to your objects which distinguishes them into groups for example

     public Type GroupType
     {  
         return typeof(...); 
     }
    

or alternatively an Enum

     public EGroupType GroupType
     {  
        return EGroupType.GroupA;    
     }

2. supply a GroupItem Style + ControlTemplate , a gridview or datagrid with it's itemssource bound to GroupItems , from the link replace the itemscontrol with a datagrid.

3.supply a Style + ControlTemplate for the GroupBox , which contains a ScrollViewer . this is something i need further checking myself i believe that something along the lines of

 <ScrollViewer>
     <ContentPresenter />
 </ScrollViewer>  

should do the trick when supplying a GroupItem template .

4.Group .

    <CollectionViewSource Source="{Binding sourceItems}" x:Key="cvs">
         <CollectionViewSource.GroupDescriptions>
               <PropertyGroupDescription PropertyName="GroupType"/>
         </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>

in your window .

    <GroupBox ItemsSource={StaticResource cvs} />
share|improve this answer
 
I'd definitely be interested to see if this works. Grouping was one of the first things I looked into, but didn't end up pursuing it further. –  climbak Sep 20 at 20:38
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.