none
VB - Activating multi selection with checkboxes in a LightSwitch grid with a one-liner

    Question

  • Paul van Bladel published the following:

    Activating Multi Seclition with Checkboxes in a Lightswtich grid with a one-liner

    Unfortunately, for me, this is in C#.  Can someone guide me on the steps I would need to following to make this work in VB?  I'm really new to many of these concepts and I'm getting stuck on what steps to follow to make this work in a VB Lightswitch app.

    Yes, I did ask Paul, but he is not able to assist as he doesn't know VB.

    This appears to be exactly what I need, but I'm stuck.

    Thanks in advance for helping point me in the right direction,

    Jennifer

    Friday, April 26, 2013 11:41 PM

Answers

  • Hi Jennifer,

    Here's Paul's extension method in VB.

    Option Strict On
    
    Imports System.Collections.ObjectModel
    Imports System.Runtime.CompilerServices
    Imports System.Windows.Markup
    Imports Microsoft.LightSwitch.Client
    
    Namespace LightSwitchApplication
        Module MultiSelectGridExtensions
    
            <Extension()>
            Public Sub AddCheckBoxColumnForMultiSelection(Of T As {Class, IEntityObject})(
                ByVal gridProxy As IContentItemProxy,
                ByVal selectedItems As ObservableCollection(Of T))
    
                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)
    
                        AddHandler dataGrid.LoadingRow, New EventHandler(Of DataGridRowEventArgs)(
                            Sub(s2, e2)
                                Dim column = dataGrid.Columns(0)
                                Dim checkBox As CheckBox = TryCast(column.GetCellContent(e2.Row), CheckBox)
                                Dim currentRowItem = TryCast(e2.Row.DataContext, T)
                                If (currentRowItem IsNot Nothing) Then
                                    checkBox.IsChecked = selectedItems.Contains(currentRowItem)
                                End If
    
                                AddHandler checkBox.Click,
                                    Sub(s3, e3)
                                        Dim selectedItem = TryCast(dataGrid.SelectedItem, T)
                                        If (selectedItem Is Nothing) Then
                                            Return
                                        End If
                                        If (Not checkBox.IsChecked.HasValue Or Not checkBox.IsChecked.Value) Then
                                            selectedItems.Remove(selectedItem)
                                        Else
                                            If (Not selectedItems.Contains(selectedItem)) Then
                                                selectedItems.Add(selectedItem)
                                            End If
                                        End If
                                        TriggerCanExecute(visualCollection)
                                    End Sub
                            End Sub)
    
                        Dim col = New DataGridTemplateColumn()
                        Dim xaml = "<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""><CheckBox/></DataTemplate>"
                        Dim dataTemplate = TryCast(XamlReader.Load(xaml), DataTemplate)
                        col.CellTemplate = dataTemplate
                        dataGrid.Columns.Insert(0, col)
    
                        RemoveHandler gridProxy.ControlAvailable, gridProxy_ControlAvailable
                    End Sub
    
                AddHandler gridProxy.ControlAvailable, gridProxy_ControlAvailable
            End Sub
    
            Private Sub TriggerCanExecute(ByVal visualCollection As IVisualCollection)
                ' This will make sure that CanExecute is triggered by 
                ' changing the Visual Collection's Selected Item, then change it back.
                ' Not elegant, but no other option...
                Dim currentItem = visualCollection.SelectedItem
                Dim collection = TryCast(visualCollection, IEnumerable(Of IEntityObject))
    
                If (Not visualCollection.SelectedItem.Equals(collection.Last())) Then
                    visualCollection.SelectedItem = collection.Last()
                Else
                    visualCollection.SelectedItem = collection.First()
                End If
                visualCollection.SelectedItem = currentItem
            End Sub
    
        End Module
    End Namespace

    You will need to:

    1. Switch to File View and add a VB Code file to the Silverlight Client Project.
    2. Copy/paste the VB code above to that file.
    3. Use it in your screen.

    For reference, here's the user code in VB, on a Customers screen

    Namespace LightSwitchApplication
    
        Public Class EditableCustomersGrid
            Dim selectedCustomers As System.Collections.ObjectModel.ObservableCollection(Of Customer) =
                New System.Collections.ObjectModel.ObservableCollection(Of Customer)()
    
            Private Sub EditableCustomersGrid_InitializeDataWorkspace(saveChangesTo As List(Of Microsoft.LightSwitch.IDataService))
                Me.FindControl("grid").AddCheckBoxColumnForMultiSelection(Of Customer)(selectedCustomers)
            End Sub
    
            Private Sub Method_CanExecute(ByRef result As Boolean)
                result = Me.Customers.SelectedItem IsNot Nothing AndAlso Me.selectedCustomers.Count >= 1
            End Sub
    
            Private Sub Method_Execute()
                For Each item In Me.selectedCustomers
                    Me.ShowMessageBox(item.CompanyName)
                Next
            End Sub
        End Class
    
    End Namespace

    Full credit to Paul, of course.

    Best regards,
    Huy Nguyen

    Monday, April 29, 2013 8:47 PM

All replies

  • Hi Jennifer,

    Here's Paul's extension method in VB.

    Option Strict On
    
    Imports System.Collections.ObjectModel
    Imports System.Runtime.CompilerServices
    Imports System.Windows.Markup
    Imports Microsoft.LightSwitch.Client
    
    Namespace LightSwitchApplication
        Module MultiSelectGridExtensions
    
            <Extension()>
            Public Sub AddCheckBoxColumnForMultiSelection(Of T As {Class, IEntityObject})(
                ByVal gridProxy As IContentItemProxy,
                ByVal selectedItems As ObservableCollection(Of T))
    
                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)
    
                        AddHandler dataGrid.LoadingRow, New EventHandler(Of DataGridRowEventArgs)(
                            Sub(s2, e2)
                                Dim column = dataGrid.Columns(0)
                                Dim checkBox As CheckBox = TryCast(column.GetCellContent(e2.Row), CheckBox)
                                Dim currentRowItem = TryCast(e2.Row.DataContext, T)
                                If (currentRowItem IsNot Nothing) Then
                                    checkBox.IsChecked = selectedItems.Contains(currentRowItem)
                                End If
    
                                AddHandler checkBox.Click,
                                    Sub(s3, e3)
                                        Dim selectedItem = TryCast(dataGrid.SelectedItem, T)
                                        If (selectedItem Is Nothing) Then
                                            Return
                                        End If
                                        If (Not checkBox.IsChecked.HasValue Or Not checkBox.IsChecked.Value) Then
                                            selectedItems.Remove(selectedItem)
                                        Else
                                            If (Not selectedItems.Contains(selectedItem)) Then
                                                selectedItems.Add(selectedItem)
                                            End If
                                        End If
                                        TriggerCanExecute(visualCollection)
                                    End Sub
                            End Sub)
    
                        Dim col = New DataGridTemplateColumn()
                        Dim xaml = "<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""><CheckBox/></DataTemplate>"
                        Dim dataTemplate = TryCast(XamlReader.Load(xaml), DataTemplate)
                        col.CellTemplate = dataTemplate
                        dataGrid.Columns.Insert(0, col)
    
                        RemoveHandler gridProxy.ControlAvailable, gridProxy_ControlAvailable
                    End Sub
    
                AddHandler gridProxy.ControlAvailable, gridProxy_ControlAvailable
            End Sub
    
            Private Sub TriggerCanExecute(ByVal visualCollection As IVisualCollection)
                ' This will make sure that CanExecute is triggered by 
                ' changing the Visual Collection's Selected Item, then change it back.
                ' Not elegant, but no other option...
                Dim currentItem = visualCollection.SelectedItem
                Dim collection = TryCast(visualCollection, IEnumerable(Of IEntityObject))
    
                If (Not visualCollection.SelectedItem.Equals(collection.Last())) Then
                    visualCollection.SelectedItem = collection.Last()
                Else
                    visualCollection.SelectedItem = collection.First()
                End If
                visualCollection.SelectedItem = currentItem
            End Sub
    
        End Module
    End Namespace

    You will need to:

    1. Switch to File View and add a VB Code file to the Silverlight Client Project.
    2. Copy/paste the VB code above to that file.
    3. Use it in your screen.

    For reference, here's the user code in VB, on a Customers screen

    Namespace LightSwitchApplication
    
        Public Class EditableCustomersGrid
            Dim selectedCustomers As System.Collections.ObjectModel.ObservableCollection(Of Customer) =
                New System.Collections.ObjectModel.ObservableCollection(Of Customer)()
    
            Private Sub EditableCustomersGrid_InitializeDataWorkspace(saveChangesTo As List(Of Microsoft.LightSwitch.IDataService))
                Me.FindControl("grid").AddCheckBoxColumnForMultiSelection(Of Customer)(selectedCustomers)
            End Sub
    
            Private Sub Method_CanExecute(ByRef result As Boolean)
                result = Me.Customers.SelectedItem IsNot Nothing AndAlso Me.selectedCustomers.Count >= 1
            End Sub
    
            Private Sub Method_Execute()
                For Each item In Me.selectedCustomers
                    Me.ShowMessageBox(item.CompanyName)
                Next
            End Sub
        End Class
    
    End Namespace

    Full credit to Paul, of course.

    Best regards,
    Huy Nguyen

    Monday, April 29, 2013 8:47 PM
  • Huy Nguyen,

    I can't thank you enough for this!!!  I wish I could repay you somehow.  You have saved me many hours trying to figure this out.  It took me just a couple of minutes to apply to my screen and to see it start work. 

    Have a great week!!!

    Jennifer

    Monday, April 29, 2013 9:49 PM
  • Hi Jennifer,

    I'm glad I was able to help. VB was my starting language so I enjoyed the opportunity to brush up on the language again :)

    Best regards,
    Huy

    Tuesday, April 30, 2013 4:24 AM
  • Hi,

    Everything works to the Point using execute or can_execute.

    Cannot perform any action after selected items in the grid.

    Used your code correctly and changed any reference to the right controle and grid and so on.

    Whats wrong here.

    Made the extnsion as a Module not class, right or wrong?

    regards

    Sven


    Sven Elm

    Tuesday, April 30, 2013 5:59 AM
  • It will not work using a modal window....

    If you do and selects. Nothing happens. Close modal window. Close the current screen.

    Open again and the application throws an error saying that the screen havn´t loaded yet.

    Any thoughts?

    Sven


    Sven Elm

    Tuesday, April 30, 2013 6:19 AM
  • It will not work using a modal window....

    If you do and selects. Nothing happens. Close modal window. Close the current screen.

    Open again and the application throws an error saying that the screen havn´t loaded yet.

    Any thoughts?

    Sven


    Sven Elm

    It works in a ordinary screen though.

    Sven


    Sven Elm

    Tuesday, April 30, 2013 6:19 AM
  • Hi again,

    It throws the same error even on a ordinary screen.

    Open it (tab). Do nothing. Close, reopen and then the error. Dispatcher has stopped.

    To bad.

    Sven


    Sven Elm

    Tuesday, April 30, 2013 6:23 AM
  • Hi,

    Made it work.

    Placed Another code Before on screen and that made it messy...

    Fixed. Sorry!

    Sven


    Sven Elm

    Tuesday, April 30, 2013 1:30 PM
  • Hi Sven,
    Is it working in model window too? I have couple of challenges. As you described above, multiselect  checkbox doesn't works in model window for the first time. User needs to close and reopen model window, second time onwards, to make it work. I noticed "LoadingRow" event is now firing, because code to add check box is in ControlAvailable event and grid LoadingRow event fires before controlavailable event. The solution I came up is when user clicks “ok” button in model window, wrote code to evaluate selected rows. This solution doesn't works when grid has multiple pages, only current page selection records will be returned. Do you have any better solution?

    In ordinary screen, if the grid has only one row this is doesn't works. I wrote code code similar as above.

    Thanks,
    Suneel

    Friday, August 30, 2013 6:31 PM
  • Hi, No sorry I have not a solution for the modal window. Tried many thinga, but no luck. Only uses this in ordinary screens. Good luck and if you find a way pleace let me know. Regards Sven

    Sven Elm If you found this post helpful, please “Vote as Helpful”

    Friday, August 30, 2013 7:17 PM
  • Does anybody know if it's possible to programmatically untick the checkbox in Method_Execute so that another set of selections can be made without the user having to manually untick them?

    Phil

    Monday, September 23, 2013 3:17 PM