locked
How do you keep a datagrid sorted after a user changes a value? RRS feed

  • Question

  • I have a Data Grid bound to a table with an "Order" column. Initially the data grid is sorted. There are up and down commands that change the order value of the selected item. 

    Unless I .OrderBy() the data bound item, .Save(), and .Refresh() the screen, the data grid will become unsorted if the user pushes up or down.

    I do not want to .Save() because validation errors may occur.

    Been stuck for a few days on this so am quite frustrated =(


    • Edited by Lynart Monday, November 10, 2014 8:42 PM
    Monday, November 10, 2014 7:31 PM

Answers

  • You can achieve this by manipulating the DataGrid directly. No need to save and refresh data.

    First, declare a module level variable to hold the grid.

    Private WithEvents mobjTeamMembersGrid As DataGrid

    In the Screen_Created event handle the ControlAvailable event for the grid, putting the grid control into your variable and call the Sort routine.

    Private Sub TeamMemberGrid_ControlAvailable(sender As Object, e As ControlAvailableEventArgs)
        mobjTeamMembersGrid = DirectCast(e.Control, DataGrid)
        SortTeamMembersGrid()
    End Sub
    
    The Sort routine gets the PagedCollectionView of the data being shown in the grid and applies the SortDescriptions you want to sort the grid into the order you require. It then sets the grid to show the newly sorted view.
    Private Sub SortTeamMembersGrid()
        Dispatchers.Main.BeginInvoke(Sub()
                                         Dim objView As New PagedCollectionView(mobjTeamMembersGrid.ItemsSource)
                                         Dim objCurrent As Object = objView.CurrentItem
     
                                         Using objView.DeferRefresh
                                             objView.SortDescriptions.Clear()
     
                                             objView.SortDescriptions.Add(New SortDescription("MembershipType.DisplayOrder", ListSortDirection.Ascending))
                                             objView.SortDescriptions.Add(New SortDescription("MembershipLevel", ListSortDirection.Ascending))
                                             objView.SortDescriptions.Add(New SortDescription("StaffMember.Name", ListSortDirection.Ascending))
                                         End Using
     
                                         objView.MoveCurrentTo(objCurrent)
                                         mobjTeamMembersGrid.ItemsSource = objView
                                     End Sub)
    End Sub

    Call this Sort routine whenever the clicks the up/down buttons to resort the grid after changing the order values.

    There are a couple of other wrinkles...

    You will probably need to remember which row was selected and reselect it after sorting so the user can click up/down multiple times to move one row up or down by many steps.

    Private Sub SortAndSelect(ByVal objThis As TeamMember)
        SortTeamMembersGrid()
        mobjTeamMembersGrid.SelectedItem = objThis
     
        Me.Details.Dispatcher.BeginInvoke(Sub()
                                              TeamMembers.SelectedItem = objThis
                                          End Sub)
    End Sub
    And on first opening the form the sort order may not be quite right. I got round this by setting up a timer to fire after half a second and calling the Sort routine from there.

    Dim WithEvents mobjTimer As New Windows.Threading.DispatcherTimerWith {.Interval = NewTimeSpan(0, 0, 0, 0, 500)}

    Private Sub mobjTimer_Tick(sender As Object, e As EventArgs) Handles mobjTimer.Tick     mobjTimer.Stop()     Me.Details.Dispatcher.BeginInvoke(Sub()                                           SortTeamMembersGrid()                                       End Sub) End Sub


        

    Simon Jones
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    • Marked as answer by Lynart Monday, November 17, 2014 4:05 PM
    Saturday, November 15, 2014 9:54 AM

All replies

  • Have you tried to write code in TestQuery_PreprocessQuery like:

    partial void TestQuery_PreprocessQuery(ref IQueryable<Label> query)
    {
        query = query.OrderBy(c => c.Order);
    }
    

    Also there has been some considerations about calculated fields, relational fields and resorting. you can take a look at this Lightswitch grid sort problem

    Tuesday, November 11, 2014 2:37 AM
    • Edited by porofessn Tuesday, November 11, 2014 2:41 AM
    Tuesday, November 11, 2014 2:40 AM
  • Have you tried to write code in TestQuery_PreprocessQuery like:

    partial void TestQuery_PreprocessQuery(ref IQueryable<Label> query)
    {
        query = query.OrderBy(c => c.Order);
    }
    

    Also there has been some considerations about calculated fields, relational fields and resorting. you can take a look at this

    This will sort the datagrid upon initially load but not after an order value is changed unless the entire datagrid is saved.
    Tuesday, November 11, 2014 1:26 PM
  • hi,

    have you tried these??

    From my understanding, if I go this route, I'd need to write the grid into an xml file on the local machine?

    There has got to be a less hacky way of doing this.

    Thursday, November 13, 2014 1:54 PM
  • you could try to use Global Variable  to store the sorted data

    you can  see:

    http://www.c-sharpcorner.com/UploadFile/18ddf7/global-variable-in-lightswitch-2012/

    Friday, November 14, 2014 3:31 AM
  • You can achieve this by manipulating the DataGrid directly. No need to save and refresh data.

    First, declare a module level variable to hold the grid.

    Private WithEvents mobjTeamMembersGrid As DataGrid

    In the Screen_Created event handle the ControlAvailable event for the grid, putting the grid control into your variable and call the Sort routine.

    Private Sub TeamMemberGrid_ControlAvailable(sender As Object, e As ControlAvailableEventArgs)
        mobjTeamMembersGrid = DirectCast(e.Control, DataGrid)
        SortTeamMembersGrid()
    End Sub
    
    The Sort routine gets the PagedCollectionView of the data being shown in the grid and applies the SortDescriptions you want to sort the grid into the order you require. It then sets the grid to show the newly sorted view.
    Private Sub SortTeamMembersGrid()
        Dispatchers.Main.BeginInvoke(Sub()
                                         Dim objView As New PagedCollectionView(mobjTeamMembersGrid.ItemsSource)
                                         Dim objCurrent As Object = objView.CurrentItem
     
                                         Using objView.DeferRefresh
                                             objView.SortDescriptions.Clear()
     
                                             objView.SortDescriptions.Add(New SortDescription("MembershipType.DisplayOrder", ListSortDirection.Ascending))
                                             objView.SortDescriptions.Add(New SortDescription("MembershipLevel", ListSortDirection.Ascending))
                                             objView.SortDescriptions.Add(New SortDescription("StaffMember.Name", ListSortDirection.Ascending))
                                         End Using
     
                                         objView.MoveCurrentTo(objCurrent)
                                         mobjTeamMembersGrid.ItemsSource = objView
                                     End Sub)
    End Sub

    Call this Sort routine whenever the clicks the up/down buttons to resort the grid after changing the order values.

    There are a couple of other wrinkles...

    You will probably need to remember which row was selected and reselect it after sorting so the user can click up/down multiple times to move one row up or down by many steps.

    Private Sub SortAndSelect(ByVal objThis As TeamMember)
        SortTeamMembersGrid()
        mobjTeamMembersGrid.SelectedItem = objThis
     
        Me.Details.Dispatcher.BeginInvoke(Sub()
                                              TeamMembers.SelectedItem = objThis
                                          End Sub)
    End Sub
    And on first opening the form the sort order may not be quite right. I got round this by setting up a timer to fire after half a second and calling the Sort routine from there.

    Dim WithEvents mobjTimer As New Windows.Threading.DispatcherTimerWith {.Interval = NewTimeSpan(0, 0, 0, 0, 500)}

    Private Sub mobjTimer_Tick(sender As Object, e As EventArgs) Handles mobjTimer.Tick     mobjTimer.Stop()     Me.Details.Dispatcher.BeginInvoke(Sub()                                           SortTeamMembersGrid()                                       End Sub) End Sub


        

    Simon Jones
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    • Marked as answer by Lynart Monday, November 17, 2014 4:05 PM
    Saturday, November 15, 2014 9:54 AM
  • Thanks Simon.

    It sounds feasible. Will try it out and get back to you.

    And at DuokLIck, I'm going to be as nice as possible saying this; please fully understand the question before trying to answer. You copied and pasted your stuff from another thread. Most of it wasn't relevant and you are just padding your post count.



    • Edited by Lynart Monday, November 17, 2014 6:11 PM
    Monday, November 17, 2014 4:07 PM