none
Grouping data within a standard LightSwitch v1 DataGrid RRS feed

  • Question

  • Hello

    I am looking to see if it is possible to group the data that is displayed in a standard datagrid as per this screenshot and article posted on a c# help website. The screenshot grouping is based on country but I will be wanting it grouped by week number.

    This is grouped by Country but I will be looking for it to be grouped by week number

    The reason I ask for it to be a standard data grid is that this will become the basis of a lot of other projects we will be creating and we dont want to have to create a custom silverlight grid for each project we do.

    Thanks in advance.

    Wednesday, June 13, 2012 11:01 AM

Answers

  • I have been struggling to get a solution whereby I could group the data within a datagrid and have comboboxes on the grid also but I have accidentally came across the answer by following two threads from Michael Washington and Tim Leung when I was trying to get the comboboxes in my custom grid populated. Then I thought "What if I can just skip the UserCode option and try it on a standard grid?" Well the steps I did are below:-

    I created a new LightSwitch project and added a table called People. In this table I added a few standard fields (FirstName, LastName, DoB, Gender and EmailAddress) and then saved it

    Next I created a  new Editable grid screen and put some test data within it (I chose the Filntstones and Chris Rock)

    Standard Grid with standard DataAs you can see, a standard grid with standard data. Now, what if we could group by Gender? So next I went back to the Screen and selected the _Created Event. I then added the reference System.Windows.Controls.Data to the screen and then entered the following code.

            IContentItemProxy myDGrid;
    
            partial void StandardGrid_Created()
            {
                // Write your code here.
                myDGrid = this.FindControl("grid"); //The Name of the grid
                myDGrid.ControlAvailable += new EventHandler<ControlAvailableEventArgs>(myDGrid_ControlAvailable);
            }
    
            void myDGrid_ControlAvailable(object sender, ControlAvailableEventArgs e)
            {
                PagedCollectionView view = new PagedCollectionView(((System.Windows.Controls.DataGrid)e.Control).ItemsSource);
                using (view.DeferRefresh())
                {
                    view.GroupDescriptions.Clear();
                    view.SortDescriptions.Add(new SortDescription("LastName", ListSortDirection.Ascending));  //What do you want to order by
                    view.GroupDescriptions.Add(new PropertyGroupDescription("Gender"));  //WHat you want to group by
                }
                ((System.Windows.Controls.DataGrid)e.Control).ItemsSource = view;
            }
    Once you hit F5 an amazing thing happens....
    Grouped By Gender!

    As you can see, this is a Standard Data Grid that has been grouped by one of the columns without any plug-in or Silverlight Code needed :)

    If you find this helpful PLEASE mark it as Helpful. This has been about a week of my life I have lost to this.

    • Marked as answer by Otis Ranger Monday, June 25, 2012 6:29 PM
    Monday, June 25, 2012 6:29 PM

All replies

  • Hi,

    if you do not want to build a costum grid you can use a third party grid:

    http://www.infragistics.com/dotnet/netadvantage/lightswitch/grid.aspx#Overview

    http://www.componentone.com/SuperProducts/FlexGridLightSwitch/

    The infragistic and the component one grid you can install as extension, so you do not need visual studio pro edition or higher and it is very comfortable. It is also possible to use telerik controls:

    http://www.telerik.com/products/silverlight/resources/lightswitch-support.aspx

    Or here is a blog post how to use devexpress grid:

    http://lightswitchspecial.blogspot.in/2012/03/integrate-devexpress-silverlight-grid.html

    But you need visual studio pro edition or higher to do this.

    Hope this will help you.

    • Proposed as answer by Simon Jones [MSDL] Wednesday, June 13, 2012 11:34 AM
    • Marked as answer by Otis Ranger Wednesday, June 13, 2012 12:25 PM
    • Unmarked as answer by Otis Ranger Monday, June 25, 2012 6:09 PM
    Wednesday, June 13, 2012 11:11 AM
  • Hi

    By Default Group By is not supported by lightswitch. Either you have to use some of the custom control provided by Dragonalw or you can hook up a WCF RIA Service to achieve the result.

    Here is a sample lightswitch application demonstrated on GroupBy by Eric.

    Regards...


    Rashmi Ranjan Panigrahi

    Wednesday, June 13, 2012 12:09 PM
  • Oh well, I did think that it might not be possible as I had been struggling with it a bit.

    The downside to the answer given by Dragonlaw is that it is hard to justify spending more money on something that will be updated in a few months when we need the solution now. I think I will have to bite the bullet and create a custom grid for each project and then provide this to others when they create their own projects.

    Thanks all for your help.


    EDIT: Whilst looking for the best way to create the datagrid I came across Michael's post about creating a control extension. I think that this is the best "free"
    • Edited by Otis Ranger Wednesday, June 13, 2012 1:03 PM Further reading. Hope it helps
    Wednesday, June 13, 2012 12:28 PM
  • I have been struggling to get a solution whereby I could group the data within a datagrid and have comboboxes on the grid also but I have accidentally came across the answer by following two threads from Michael Washington and Tim Leung when I was trying to get the comboboxes in my custom grid populated. Then I thought "What if I can just skip the UserCode option and try it on a standard grid?" Well the steps I did are below:-

    I created a new LightSwitch project and added a table called People. In this table I added a few standard fields (FirstName, LastName, DoB, Gender and EmailAddress) and then saved it

    Next I created a  new Editable grid screen and put some test data within it (I chose the Filntstones and Chris Rock)

    Standard Grid with standard DataAs you can see, a standard grid with standard data. Now, what if we could group by Gender? So next I went back to the Screen and selected the _Created Event. I then added the reference System.Windows.Controls.Data to the screen and then entered the following code.

            IContentItemProxy myDGrid;
    
            partial void StandardGrid_Created()
            {
                // Write your code here.
                myDGrid = this.FindControl("grid"); //The Name of the grid
                myDGrid.ControlAvailable += new EventHandler<ControlAvailableEventArgs>(myDGrid_ControlAvailable);
            }
    
            void myDGrid_ControlAvailable(object sender, ControlAvailableEventArgs e)
            {
                PagedCollectionView view = new PagedCollectionView(((System.Windows.Controls.DataGrid)e.Control).ItemsSource);
                using (view.DeferRefresh())
                {
                    view.GroupDescriptions.Clear();
                    view.SortDescriptions.Add(new SortDescription("LastName", ListSortDirection.Ascending));  //What do you want to order by
                    view.GroupDescriptions.Add(new PropertyGroupDescription("Gender"));  //WHat you want to group by
                }
                ((System.Windows.Controls.DataGrid)e.Control).ItemsSource = view;
            }
    Once you hit F5 an amazing thing happens....
    Grouped By Gender!

    As you can see, this is a Standard Data Grid that has been grouped by one of the columns without any plug-in or Silverlight Code needed :)

    If you find this helpful PLEASE mark it as Helpful. This has been about a week of my life I have lost to this.

    • Marked as answer by Otis Ranger Monday, June 25, 2012 6:29 PM
    Monday, June 25, 2012 6:29 PM
  • Ot1s, congratulation for your post. Thank you to share it with us. I gave you +1.

    Here is the VB.net version:

    First, add Client project reference to System.Windowns.Controls.Data.

    Imports System.Windows.Data
    Imports System.Windows.Controls
    
    Namespace LightSwitchApplication
    
        Public Class GroupedGrid
    
            Private _grid As IContentItemProxy
    
            Private Sub GroupedGrid_Created()
                _grid = FindControl("grid")
                AddHandler _grid.ControlAvailable, AddressOf GRID_AVAILABLE
            End Sub
    
            Private Sub GRID_AVAILABLE(sender As Object, e As ControlAvailableEventArgs)
    
                Dim view As PagedCollectionView = New PagedCollectionView(CType(e.Control, DataGrid).ItemsSource)
    
                Using view.DeferRefresh()
                    view.GroupDescriptions.Clear()
    
                    ' What do you want to order by
                    view.SortDescriptions.Add(New SortDescription("LastName", ListSortDirection.Ascending))
    
                    ' What you want to group by
                    view.GroupDescriptions.Add(New PropertyGroupDescription("Gender"))
                End Using
    
                CType(e.Control, DataGrid).ItemsSource = view
            End Sub
    
        End Class
    
    End Namespace
    Best regards,


    Ciro

    Monday, June 25, 2012 11:28 PM
  • Hi Ot1s,

    It is really amazing datagrid.

    can it  be possible to get  group totals   for each group ?

    Thank you for this good working and  yours sharing.

    Regards.


    Monday, June 25, 2012 11:35 PM
  • Yes, I was going to say that if the Silverlight DataGrid (which LS uses) can do something, then you can do it in LightSwitch, you just usually have to manuliplate it in code, as you have.

    Well done!

    +1


    Yann - LightSwitch Central - Click here for FREE Themes, Controls, Types and Commands
     
    If you find a reply helpful, please click "Vote as Helpful", if a reply answers your question, please click "Mark as Answer"
     
    By doing this you'll help people find answers faster.

    Tuesday, June 26, 2012 1:21 AM
    Moderator
  • Hi Ot1s,

    It is really amazing datagrid.

    can it  be possible to get  group totals   for each group ?

    Thank you for this good working and  yours sharing.

    Regards.


    Thank you for the +1. I'm sure it is possible but I am unable to discover this due to workload. However, on my travels to find the customising of the DataGrid RowGroup Headers I found this article that I think can be used with a little bit of effort :)

    http://leeontech.wordpress.com/2010/02/01/summary-row-in-datagrid/


    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)

    Thursday, June 28, 2012 8:25 AM
  • An important note to anyone who uses this code.

    When I was testing this I came up with an error stating Object not set to an Instance of Object yet everything was working as expected. In my application I am adding rows to the datagrid in code (which was working fine before the grouping) and once you OK'ed the error the new rows showed as expected. However, this meant that every other click on the DataGrid ended up showing the error.

    The solution? Make sure that if you are adding rows to the DataGrid in code the first field you populate is the field you are grouping on!

    As I type this it seems obvious but if I had known this earlier there would have been a lot less heartache :)


    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)

    Thursday, June 28, 2012 8:30 AM
  • Today I am on a roll! When I last left you I had got the standard DataGrid Grouped but had not styled the headings (See first screenshot)

    Before Colouring (removed Add new row also)

    Well after looking at how I handled colouring the rows in the project (see my other posts for how-to's) I applied the same principal to the headings and the results are plain to see!

    And they say red and green should not be seen

    So how to do this. Firstly I went to the design screen and selected the _InitializeDataWorkspace code. Then I added Using System.Windows.Media; to the top of the page. Next I added the following code

            partial void StandardGrid_InitializeDataWorkspace(List<IDataService> saveChangesTo)
            {
                // Write your code here.
                Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(() =>
                {
                    var proxy = this.FindControl("grid");
                    proxy.ControlAvailable += new EventHandler<ControlAvailableEventArgs>(proxy_ControlAvailable);
                });
            }
            void proxy_ControlAvailable(object sender, ControlAvailableEventArgs e)
            {
                var ctrl = (DataGrid)e.Control;
                ctrl.LoadingRowGroup += new EventHandler<DataGridRowGroupHeaderEventArgs>(ctrl_LoadingRowGroup);
            }
            void ctrl_LoadingRowGroup(object sender, DataGridRowGroupHeaderEventArgs e)
            {
                DataGrid grid = (DataGrid)sender;
                DataGridRowGroupHeader row = new DataGridRowGroupHeader();
                row = e.RowGroupHeader;
                row.Background = new SolidColorBrush(Color.FromArgb(255, 0, 255, 0));
                row.Foreground = new SolidColorBrush(Colors.Red);
                row.Height = 28;
                row.FontFamily = new FontFamily("Arial");
                row.FontSize = 14;
            }
    As you can see this works beautifully and to make it look more presentable you just need to select better colour pairings. I am sure that if you handled all of this better you can dynamically change the colours using iValueConverters but as this satisfies my current project needs I shall leave it here. Happy Colouring :)


    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)

    Thursday, June 28, 2012 9:02 AM
  • Well done!

    A couple of things though.

    These two lines:

    DataGridRowGroupHeader row = new DataGridRowGroupHeader();
    row = e.RowGroupHeader;
    

    Can be replaced with:

    var row = e.RowGroupHeader;
    

    That other line creates a new DataGridRowGroupHeader, but you do nothing with it, & simply replace its contents with e.RowGroupHeader anyway.

    The other thing that you may not have realised. If you style things "manually" (in code) lke this, you risk that whatever colors you choose to use in code may not match, or "look right", if you change the theme.

    That's the reason why my GroupLayout control is "themed". Whenever the theme is changed the colors in the control automatically change as well.


    Yann - LightSwitch Central - Click here for FREE Themes, Controls, Types and Commands
     
    If you find a reply helpful, please click "Vote as Helpful", if a reply answers your question, please click "Mark as Answer"
     
    By doing this you'll help people find answers faster.

    Thursday, June 28, 2012 9:26 AM
    Moderator
  • Thanks for the correction. I got a little too excited and didn't remove all the code that I was supposed to :$

    I also agree with your theming point. I have to admit that at the moment I am a humble code monkey who writes code but if this was to be given to a PA or secretary to "manage" then these parts could become a bit nasty. Currently this meets my needs (not in the red and green mind) and anyone who has been following this thread and copying the code should take note of Yann's words.


    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)

    Thursday, June 28, 2012 9:35 AM
  • Fantastic! +1 from me for at least two of these posts :)

    This is the sort of stuff that proves you can do just about anything with LS! Keep up the good work.


    FREE custom controls for Lightswitch! A collection of useful controls for Lightswitch developers. Download from the Visual Studio Gallery.

    If you're really bored, you could read about my experiments with .NET and some of Microsoft's newer technologies at http://dotnetwhatnot.pixata.co.uk/

    Monday, July 2, 2012 10:51 AM
  • I have a data grid and detail section in a lightswitch screen. When user select different row in data grid, information in detail section changes accordingly.

    But after I added grouping in data grid, detail section does not change any more.

    Thursday, October 10, 2013 7:44 PM
  • Hello

    I'm so pleased that this post is still helping people out :) I think that you will have to invoke the .SelectionChanged event. I can add a basic bit of code here but dont have the time to test it, sorry.

    Within the _ControlAvailable event you need to add the following line:-

    ctrl.SelectionChanged += new SelectionChangedEventHandler(ctrl_SelectionChanged);

    You will then have to add a block of code to invoke when the selection changes:-

            void ctrl_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                if (e.AddedItems.Count > 0) //Something is selected
                {
                    var row = e.AddedItems[0]; //Set something to the (first) selected row
                    //Do Something with row....maybe set the selected item of the dataset to it???
                }
            }

    If I get a chance this weekend I may mock up something with the test above but until then I hope this helps :)

    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)

    Friday, October 11, 2013 3:03 PM
  • This is outstanding!! I can't believe I missed it before somehow. Questions: 1. How to change the display name used for the PropertyGroupDescription? My propertyName itself is not descriptive enough, I would like to use the Property's displayName as Group header. 2. I receive an error when trying to sort on some of the other fields in the grid: "At least one object must implement IComparable". Any way to fix that? Thanks so much for a great solution.
    Friday, October 11, 2013 6:51 PM
  • I have a data grid and detail section in a lightswitch screen. When user select different row in data grid, information in detail section changes accordingly.

    But after I added grouping in data grid, detail section does not change any more.

    Hello Shelia

    I have had a little play and I have a solution for you. Within the ControlAvailable event you will need to add the following two lines to the end

    var ctrl = (DataGrid)e.Control;
                ctrl.SelectionChanged += new SelectionChangedEventHandler(ctrl_SelectionChanged);

    You will then need to add the following code snippet within the page...

    void ctrl_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count > 0) //Something is selected { var row = e.AddedItems[0]; //Set something to the (first) selected row var selection = (from item in this.PeopleSet
    where item.Id.ToString() == row.ToString()
    select item).FirstOrDefault(); //Find the selected row within your dataset

    this.PeopleSet.SelectedItem = selection; //Set your dataset to the selected row!!!!! } }

    Hit F5 et voila! It works!!!!
    Now there is a caveats to this code.....firstly it requires you to set the summary property of your table to be the ID field (as whatever the summary field is on the table is what is selected within the e.AddedItems) .

    This is the best Idea I can come up with at the moment, but if it helps show your appreciation by voting on it :)


    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)


    • Edited by Otis Ranger Monday, October 14, 2013 4:03 PM Im stupid!!!!
    Monday, October 14, 2013 3:45 PM
  • Hello

    Thanks for the feedback :)

    Not tried to change the propertygroupdescription myself but it must be possible. If i get a moment i may give it a go.

    On your second question do you mean you get the error whilst the app is running or when you have coded the column to be sorted and it doesnt run??


    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)

    Monday, October 14, 2013 3:51 PM
  • Ot1s, congratulation for your post. Thank you to share it with us. I gave you +1 again.

    Here is the VB.net version:

    First, add Client project reference to System.Windowns.Controls.Data.

    Imports System.Windows.Data
    Imports System.Windows.Controls
    Imports Microsoft.LightSwitch.Threading.Dispatchers
    Imports System.Windows.Media
    
    Namespace LightSwitchApplication
    
        Public Class GroupedGrid
    
            Private _grid As IContentItemProxy
    
            Private Sub GroupedGrid_InitializeDataWorkspace(saveChangesTo As System.Collections.Generic.List(Of Microsoft.LightSwitch.IDataService))
    
                Main.BeginInvoke(Sub()
                                     Dim proxy = Me.FindControl("grid")
                                     AddHandler proxy.ControlAvailable, AddressOf GRID_AVAILABLE
                                 End Sub)
            End Sub
    
    
            Private Sub GroupedGrid_Created()
                _grid = FindControl("grid")
                AddHandler _grid.ControlAvailable, AddressOf GRID_AVAILABLE
            End Sub
    
    
            Private Sub GRID_AVAILABLE(sender As Object, e As ControlAvailableEventArgs)
    
                Dim view As PagedCollectionView = New PagedCollectionView(CType(e.Control, DataGrid).ItemsSource)
    
                Using view.DeferRefresh()
                    view.GroupDescriptions.Clear()
    
                    ' What do you want to order by
                    view.SortDescriptions.Add(New SortDescription("LastName", ListSortDirection.Ascending))
    
                    ' What you want to group by
                    view.GroupDescriptions.Add(New PropertyGroupDescription("Gender"))
                End Using
    
                CType(e.Control, DataGrid).ItemsSource = view
    
    
                Dim myGrid = CType(e.Control, DataGrid)
                AddHandler myGrid.LoadingRowGroup, AddressOf ctrl_LoadingRowGroup
            End Sub
    
            Private Sub ctrl_LoadingRowGroup(sender As Object, e As DataGridRowGroupHeaderEventArgs)
    
                'Dim grid As DataGrid = DirectCast(sender, DataGrid)
                'Dim row As New DataGridRowGroupHeader()
    
                Dim row = e.RowGroupHeader
                row.Background = New SolidColorBrush(Color.FromArgb(255, 0, 255, 0))
                row.Foreground = New SolidColorBrush(Colors.Red)
                row.Height = 28
                row.FontFamily = New FontFamily("Arial")
                row.FontSize = 14
    
            End Sub
    
        End Class
    
    End Namespace
    


    Ciro

    Monday, October 14, 2013 7:59 PM
  • hi!

    very nice example, also my votes for it..

    i guess the error that Hessc reported is when you try to group on navigation property (i'm getting same error in that case)..

    i also tried to create one-liner for this, i'm not experienced programmer (i'm self-learned lalala) so i believe that there is a way to improve it (basically i took Paul van Bladel multi select grid checkbox example translated by Huy, and glue it with this one):

    ' creates grouping in LS datagrid 
            <Extension()>
            Public Sub AddGroupHeader(Of T As {Class, IEntityObject})(
                ByVal gridProxy As IContentItemProxy,
                SortDescription As String,
                GroupDescription As String,
                Optional SumProperty As String = Nothing)
    
                Dim gridProxy_ControlAvailable As EventHandler(Of ControlAvailableEventArgs) =
                    Sub(s1, e1)
                        Dim dataGrid = TryCast(e1.Control, DataGrid)
                        Dim contentItem = TryCast(dataGrid.DataContext, IContentItem)
                        Dim visualCollection = TryCast(contentItem.Value, IVisualCollection)
    
                        Dim view As PagedCollectionView = New PagedCollectionView(CType(e1.Control, DataGrid).ItemsSource)
    
                        AddHandler dataGrid.LoadingRowGroup, New EventHandler(Of DataGridRowGroupHeaderEventArgs)(
                            Sub(s2, e2)
                                Dim grid = DirectCast(s2, DataGrid)
                                Dim row As DataGridRowGroupHeader
                                row = e2.RowGroupHeader
    
                                ' if you want to style group header
                                row.Background = New SolidColorBrush(Colors.Orange)
                                row.FontWeight = FontWeights.Bold
                                row.Height = 25
                                row.Cursor = Cursors.Hand
    
                                ' oh my can i do summary here?
                                If Not String.IsNullOrWhiteSpace(SumProperty) Then
                                    Dim currentRowGroup = TryCast(e2.RowGroupHeader.DataContext, CollectionViewGroup)
                                    Dim dum As Decimal = CDec(0.0)
                                    Try
                                        For Each el As T In currentRowGroup.items
                                            Dim result = el.Details.DisplayName
                                            dum = dum + CDec(el.Details.Properties.Item(SumProperty).Value)
                                        Next
                                    Catch ex As Exception
                                        Exit Sub
                                    End Try
    
                                    ' custom control template if u want to change look of header but you loose nice arrow
                                    Dim xaml =
                                        "<ControlTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">" &
                                            "<StackPanel Orientation=""Horizontal"" Height=""Auto"" HorizontalAlignment=""Stretch"" VerticalAlignment=""Center"" Background=""{TemplateBinding Background}"">" &
                                                "<TextBlock Margin=""10,4,4,4"" Text=""{Binding Name}"" Height=""{TemplateBinding Height}"" Foreground=""{TemplateBinding Foreground}"" TextDecorations=""Underline""/>" &
                                                "<TextBlock Margin=""4,4,4,4"" Text=""-"" Height=""{TemplateBinding Height}"" Foreground=""{TemplateBinding Foreground}""/>" &
                                                "<TextBlock Margin=""4,4,4,4"" Text=""{Binding ItemCount}"" Height=""{TemplateBinding Height}"" Foreground=""{TemplateBinding Foreground}""/>" &
                                                "<TextBlock Margin=""4,4,4,4"" Text=""zapisa."" Height=""{TemplateBinding Height}"" Foreground=""{TemplateBinding Foreground}""/>" &
                                                "<TextBlock Margin=""4,4,4,4"" Text=""Ukupno: " & dum & " kn"" Height=""{TemplateBinding Height}"" Foreground=""{TemplateBinding Foreground}""/>" &
                                            "</StackPanel>" &
                                        "</ControlTemplate>"
                                    Dim controlTemplate = TryCast(XamlReader.Load(xaml), ControlTemplate)
                                    row.Template = controlTemplate
                                End If
    
                            End Sub)
    
                        ' to synchronize selected item with original collection?
                        'AddHandler dataGrid.SelectionChanged,
                        '    Sub(s3, e3)
                        '        Dim selectedItem = TryCast(dataGrid.SelectedItem, T)
                        '        If selectedItem IsNot Nothing Then
                        '            visualCollection.SelectedItem = selectedItem
                        '        Else
                        '            visualCollection.SelectedItem = Nothing
                        '        End If
                        '        Dim lsz = view.CurrentItem
                        '    End Sub
    
                        ' also occurs when going from page to page
                        AddHandler view.CollectionChanged,
                            Sub(s4, e4)
                                Dim selectedItem = TryCast(view.CurrentItem, T)
                                If selectedItem IsNot Nothing Then
                                    If visualCollection.SelectedItem IsNot selectedItem Then
                                        visualCollection.SelectedItem = selectedItem
                                    End If
                                Else
                                    visualCollection.SelectedItem = Nothing
                                End If
                            End Sub
    
                        ' seems better than tamping to datagrid selection changed event, does not trigger on first collection load
                        AddHandler view.CurrentChanged,
                            Sub(s5, e5)
                                Dim selectedItem = TryCast(view.CurrentItem, T)
                                If selectedItem IsNot Nothing Then
                                    If visualCollection.SelectedItem IsNot selectedItem Then
                                        visualCollection.SelectedItem = selectedItem
                                    End If
                                Else
                                    visualCollection.SelectedItem = Nothing
                                End If
                            End Sub
    
                        ' apply grouping
                        Using view.DeferRefresh()
                            view.GroupDescriptions.Clear()
                            ' What do you want to order by
                            view.SortDescriptions.Add(New SortDescription(SortDescription, ListSortDirection.Ascending))
                            ' it would be nice to dynamically collect sort descriptions from original collection?
                            'For Each sd As SortDescription In visualCollection.Details.SortDescriptors
                            '    view.SortDescriptions.Add(sd)
                            'Next
                            ' What you want to group by
                            view.GroupDescriptions.Add(New PropertyGroupDescription(GroupDescription))
                        End Using
    
                        CType(e1.Control, DataGrid).ItemsSource = view
                        RemoveHandler gridProxy.ControlAvailable, gridProxy_ControlAvailable
                    End Sub
    
                AddHandler gridProxy.ControlAvailable, gridProxy_ControlAvailable
            End Sub

    tries / misses:

    - sorting works only on current page (i believe its same in original example)..

    - i tried to synchronize paged collection with visual collection so when you IE. click on edit button in datagrid header, correct item is edited..

    - tried to add summary with optional variables and custom control template, unfortunately then you loose nice arrow and original template..

    - i find that is necessary to sort visual collection for grouping to be correct (so if u grouping on "city", visual collection should be already sorted on "city")

    - group header is not updated when you change something on screen..

    - usage: in screen_creted() just do "me.FindControl("your_control").AddGroupHeader(of "your_entity") ("sort_description", "group_description", "sum_property")".. 

    hope that experienced guys can improve this and that it will be also useful for someone..

    Kivito


    Nobody expects the Spanish Inquisition! (M.P.F.C.)


    • Edited by Kivito Tuesday, October 15, 2013 8:36 AM typos
    Tuesday, October 15, 2013 8:29 AM
  • May go without saying, but adding this line will allow you to suppress the GroupBy property name.

    Result will change:

    Department: Department X (4 items)
    to
    Department X (4 items)

    row.PropertyNameVisibility = Visibility.Collapsed

    Tuesday, October 15, 2013 7:19 PM
  • After reading through all the comments (especially Kivito's in the code) I decided to have a little play and as you can see from my demo app you can indeed change the grouping AND sorting at run time! As you can see from the pictures below I have taken the same test app and added two selection criterias, one for grouping and one for sorting. I have then linked the change event on these two to affect the grouping and sorting.

    Grouped By Gender, sorted by first name *Within the group*

    Selection shown and Grouping changed!!

    This can be done by declaring the PagedCollectionView in the Partial Class and not within the ControlAvailable event and then adding the code below making sure that you call this on change of the comboboxes that contain your grouping and sorting:-

            void ChangeAndReload()
            {
                Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(() =>
                {
                    view.GroupDescriptions.Clear();
                    view.SortDescriptions.Clear();
                    view.GroupDescriptions.Add(new PropertyGroupDescription(this.Grouping)); //The Name of the Grouping Selection Box
                    view.SortDescriptions.Add(new SortDescription(this.Sorting, ListSortDirection.Ascending));  //The Name of the sorting selection box
                    view.Refresh();
                });
            }

    And that's it! Again, no extensive testing but a lot of fun trying things out from your comments and examples! I may make this sample available to people if they really want it (Make use of the SkyDrive :)) so let me know if that would be a good thing.

    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)

    Wednesday, October 16, 2013 3:40 PM
  • Hi, Otis!

    Nice improvement.

    Could you please send me the SkyDrive link to download the exemple?

    Best regards,


    Ciro

    Thursday, October 17, 2013 1:06 AM
  • Hi Otis,

    Many many thanks for the solution. I am very interested in the skydrive link.

    +1

    best wishes

    Oliver

    olimilo@gmx.net

    Thursday, October 17, 2013 2:50 AM
  • Hello All

    Here is a link to the zipped project on my SkyDrive

    DataGridGrouped

    Let me know if there are any issues


    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)

    Thursday, October 17, 2013 12:46 PM
  • Yet more +1s for you Otis!

    Good to see people are still pushing the Silverlight client. Microsoft is pushing us away from it, thankfully people like you are helping those who still want to use it.


    FREE custom controls for Lightswitch! A collection of useful controls for Lightswitch developers. Download from the Visual Studio Gallery.

    If you're really bored, you could read about my experiments with .NET and some of Microsoft's newer technologies at http://dotnetwhatnot.pixata.co.uk/

    Thursday, October 17, 2013 1:08 PM
  • Otis, thanks again to share your code with us. (+1 again)

    I made some changes, so now, you can toggle grouping via code:

    Here is the source code:

    Imports System.Windows.Data
    Imports System.Windows.Controls
    Imports Microsoft.LightSwitch.Threading.Dispatchers
    Imports System.Windows.Media
    
    Namespace LightSwitchApplication
    
        Public Class GroupedGrid_01a
    
            Private _grid As IContentItemProxy
            Private _view As PagedCollectionView
            Private _dataGrid As DataGrid
    
            Private Sub GroupedGrid_01a_InitializeDataWorkspace(saveChangesTo As System.Collections.Generic.List(Of Microsoft.LightSwitch.IDataService))
    
                Main.BeginInvoke(Sub()
                                     Dim proxy = Me.FindControl("grid")
                                     AddHandler proxy.ControlAvailable, AddressOf GRID_AVAILABLE
                                 End Sub)
            End Sub
    
    
            Private Sub GroupedGrid_01a_Created()
                _grid = FindControl("grid")
                AddHandler _grid.ControlAvailable, AddressOf GRID_AVAILABLE
            End Sub
    
    
            Private Sub GRID_AVAILABLE(sender As Object, e As ControlAvailableEventArgs)
    
                _view = New PagedCollectionView(CType(e.Control, DataGrid).ItemsSource)
                _dataGrid = CType(e.Control, DataGrid)
    
                Using _view.DeferRefresh()
                    _view.GroupDescriptions.Clear()
    
                    ' What do you want to order by
                    _view.SortDescriptions.Add(New SortDescription("LastName", ListSortDirection.Ascending))
    
                    ' What you want to group by
                    _view.GroupDescriptions.Add(New PropertyGroupDescription("Gender"))
                End Using
    
                CType(e.Control, DataGrid).ItemsSource = _view
    
    
                Dim myGrid = CType(e.Control, DataGrid)
                AddHandler myGrid.LoadingRowGroup, AddressOf ctrl_LoadingRowGroup
            End Sub
    
            Private Sub ctrl_LoadingRowGroup(sender As Object, e As DataGridRowGroupHeaderEventArgs)
    
                'Dim grid As DataGrid = DirectCast(sender, DataGrid)
                'Dim row As New DataGridRowGroupHeader()
    
                Dim row = e.RowGroupHeader
                row.Background = New SolidColorBrush(Color.FromArgb(255, 0, 255, 0))
                row.Foreground = New SolidColorBrush(Colors.Red)
                row.Height = 28
                row.FontFamily = New FontFamily("Arial")
                row.FontSize = 14
    
            End Sub
    
    
            Private Sub ChangeAndReload()
                Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(Sub()
                                                                                 If Grouping <> String.Empty Then
                                                                                     _view.GroupDescriptions.Clear()
                                                                                     _view.GroupDescriptions.Add(New PropertyGroupDescription(Me.Grouping))
                                                                                 End If
                                                                                 '
                                                                                 If Sorting <> String.Empty Then
                                                                                     _view.SortDescriptions.Clear()
                                                                                     _view.SortDescriptions.Add(New SortDescription(Me.Sorting, ListSortDirection.Ascending))
                                                                                 End If
                                                                                 '
                                                                                 _view.Refresh()
                                                                             End Sub)
            End Sub
    
            Private Sub Grouping_Changed()
                ChangeAndReload()
            End Sub
    
            Private Sub Sorting_Changed()
                ChangeAndReload()
            End Sub
    
            Private Sub CollapseGroups(groupingLevel As Integer, Optional collapseAllSublevels As Boolean = False)
    
                Main.BeginInvoke(Sub()
                                     If _dataGrid.ItemsSource Is Nothing Then
                                         Return
                                     End If
                                     Dim groups As New HashSet(Of CollectionViewGroup)()
                                     For Each item As Object In _dataGrid.ItemsSource
                                         groups.Add(_dataGrid.GetGroupFromItem(item, groupingLevel))
                                     Next
                                     For Each group As CollectionViewGroup In groups
                                         _dataGrid.CollapseRowGroup(group, collapseAllSublevels)
                                     Next
                                 End Sub)
            End Sub
    
            Private Sub ExpandGroups(groupingLevel As Integer, Optional expandAllSublevels As Boolean = False)
    
                Main.BeginInvoke(Sub()
                                     If _dataGrid.ItemsSource Is Nothing Then
                                         Return
                                     End If
                                     Dim groups As New HashSet(Of CollectionViewGroup)()
                                     For Each item As Object In _dataGrid.ItemsSource
                                         groups.Add(_dataGrid.GetGroupFromItem(item, groupingLevel))
                                     Next
                                     For Each group As CollectionViewGroup In groups
                                         _dataGrid.ExpandRowGroup(group, expandAllSublevels)
                                     Next
                                 End Sub)
            End Sub
    
    
            Private Sub ToggleGrouping_Execute()
    
                Static isCollapsed As Boolean
    
                If isCollapsed Then
                    ExpandGroups(groupingLevel:=0, expandAllSublevels:=True)
                Else
                    CollapseGroups(groupingLevel:=0, collapseAllSublevels:=True)
                End If
                '
                isCollapsed = Not isCollapsed
            End Sub
    
        End Class
    
    End Namespace
    Best regards,


    Ciro


    • Edited by Oric.CQ Friday, October 18, 2013 2:03 PM
    Friday, October 18, 2013 2:01 PM
  • Hi,

    Does anyone know how to do something similar but grouping by week.  I am looking to be able to have a user select the starting day of the week and then group the data into weeks.

    Regards,

    Ed

    Thursday, January 30, 2014 1:52 PM
  • Hello Ed

    Do you have a column that shows Week? If you do then you can use any of the examples given above. If you dont and have control over the data then you can create a computed column on the date data to group on.

    On my initial question on this thread I group by Week Commencing which is a computed column within SQL that looks at a date that i have within the data. The column has a formula to work out the start date of the week and then I group on that.

    HTH


    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)

    Thursday, January 30, 2014 3:29 PM
  • I'm not sure if I should post a new question or add to this thread, but this was a great help and am using code provided in the answer, but I have some sort of ghost record because it shows an empty Grouped row (by order number) but there is no order number listed. I tried omitting ID 0, and created a new edit grid just to check the records.

    Any thoughts?




    • Edited by MrGlimm Tuesday, April 21, 2015 3:59 AM
    Monday, April 20, 2015 5:59 AM
  • Hello MrGlimm

    I am really pleased that this post has helped you in your issue and hope that it continues to be helpful to others. Really this should have been a new question but I think that it will help others who have looked at this and used the code.

    The reason that you are getting the blank\ghost record is because you have the "Show Add new row" option on your datagrid turned on. If you look at the screenshot in the answer of this question you will see that the first row of the grid is the add new item one. If you take the tick out of the box on the screen designer when you have selected the data grid and then run the programme again you should see that your ghost problem has gone away :) 


    If you found this post helpful, please mark it as helpful. If by some chance I answered the question, please mark the question as answered. That way you will help more people like me :)

    Monday, April 20, 2015 9:09 AM
  • Oric the Toggle works great!

    Regards

    • Edited by Robjv Monday, June 20, 2016 8:44 PM
    Monday, June 20, 2016 12:51 PM