1

Couldn't the following code be done (and done better) with LINQ/func delegate? I'm fairly new to LINQ/func. I'm looping through all the controls on the form to find all the FlowLayoutPanels (they're embedded in tabs and split containers) and saving the control index information to the application settings so it can be recalled upon loading. My app allows the user to reposition their GUI/controls with drag drop. *Note, ServicingLayout is my own serializable class with info I need to restore the user's preference.

Private Sub SaveFlow(ByVal F As FlowLayoutPanel) Handles Me.FoundFlow
    For Each C As Control In F.Controls
        My.Settings.ServicingLayout.AddControl(F.Name, C.Name, F.Controls.GetChildIndex(C))
    Next
End Sub

Private Event FoundFlow(ByVal F As FlowLayoutPanel)

Private Sub SaveFlowLayouts(ByVal CC As Object)
    For Each C As Control In CC
        If TypeOf C Is FlowLayoutPanel Then RaiseEvent FoundFlow(C)
        If C.Controls.Count > 0 Then SaveFlowLayouts(C.Controls)
    Next
End Sub

Thank you!

DontFretBrett
  • 1,135
  • 3
  • 17
  • 32
  • 2
    LINQ is good when processing data through different stages, however here, you just perform some actions and For Each loops are just fine. – Olivier Jacot-Descombes Aug 07 '12 at 20:30
  • Can I suggest that you put "Option Strict On" at the top of your code? Being able to `For Each` over an `Object` is just asking for bugs to be in your code. – Enigmativity Aug 08 '12 at 01:16

1 Answers1

1

Olivier is right in suggesting that LINQ is good for processing data through filters and applying transformations, etc... it doesn't do other things (like recursion, multi-branch logic) so well.

I was kind of able to do this in LINQ, but it is ugly.

However, I would recommend stealing at least one LINQ feature... you can easily filter the ControlCollection for FlowLayoutPanel with this line (and as a bonus it's already strongly typed for you!)

Dim flowLayoutPanels = Me.Controls.OfType(Of FlowLayoutPanel)

Without further-ado... ugly LINQ.

Private Sub SaveWithLinq(ByVal CC As Control.ControlCollection)
  CC.OfType(Of FlowLayoutPanel).ToList.ForEach(
    Sub(f)
      f.Controls.Cast(Of Control).ToList.ForEach(
        Sub(c)
          My.Settings.ServicingLayout.AddControl(f.Name, c.Name,             
                                                 f.Controls.GetChildIndex(c))
        End Sub)

      If f.Controls.Count > 0 Then
        SaveWithLinq(f.Controls)
      End If
    End Sub)
End Sub

Part of the ugliness is due to the fact that Control.ControlCollection is not strongly typed (it implements IEnumerable instead of IEnumerable(Of T), so we have to tell LINQ the type of the objects in that collection (more detail here).

Community
  • 1
  • 1
Jeff B
  • 8,572
  • 17
  • 61
  • 140
  • Thanks Jeff, some great info here! Controls.OfType, Doh. Wish I knew that before. – DontFretBrett Aug 16 '12 at 17:08
  • You're welcome! I just recently discovered it too and felt the same way ;) It was introduced to me by the C#/.NET Little Wonders series of blog posts: http://geekswithblogs.net/BlackRabbitCoder/archive/2012/06/07/c.net-little-wonders-use-cast-and-typeof-to-change-sequence.aspx – Jeff B Aug 17 '12 at 12:37