Librería de Snippets para VB.NET !! (Compartan aquí sus snippets)

<< < (117/119) > >>

Eleкtro:
Dos simples métodos para ocultar y restaurar las cabeceras de las pestañas de un TabControl:



Código
''' <summary>
''' Provides extension methods for the <see cref="TabControl"/> class.
''' </summary>
<HideModuleName>
Public Module TabControlExtensions
 
   ''' ---------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Hides the tab headers of the source <see cref="TabControl"/>.
   ''' </summary>
   ''' ---------------------------------------------------------------------------------------------------
   ''' <example> This is a code example.
   ''' <code language="VB">
   ''' ' Create a TabControl instance
   ''' Dim myTabControl As New TabControl()
   '''
   ''' ' Add some tabs to the TabControl
   ''' myTabControl.TabPages.Add("Tab 1")
   ''' myTabControl.TabPages.Add("Tab 2")
   ''' myTabControl.TabPages.Add("Tab 3")
   '''
   ''' ' Display the TabControl in a Form
   ''' Me.Controls.Add(myTabControl)
   ''' myTabControl.BringToFront()
   '''
   ''' ' Hide the tab headers
   ''' myTabControl.HideTabheaders()
   ''' </code>
   ''' </example>
   ''' ---------------------------------------------------------------------------------------------------
   ''' <param name="tabControl">
   ''' The <see cref="TabControl"/> whose tab headers are to be hidden.
   ''' </param>
   ''' ---------------------------------------------------------------------------------------------------
   <Extension>
   <DebuggerStepThrough>
   Public Sub HideTabheaders(tabControl As TabControl)
       TabControlExtensions.ShowTabheaders(tabControl, TabSizeMode.Fixed, New Size(0, 1))
   End Sub
 
   ''' ---------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Shows the tab headers of the source <see cref="TabControl"/>.
   ''' </summary>
   ''' ---------------------------------------------------------------------------------------------------
   ''' <example> This is a code example.
   ''' <code language="VB">
   ''' ' Create a TabControl instance
   ''' Dim myTabControl As New TabControl()
   '''
   ''' ' Add some tabs to the TabControl
   ''' myTabControl.TabPages.Add("Tab 1")
   ''' myTabControl.TabPages.Add("Tab 2")
   ''' myTabControl.TabPages.Add("Tab 3")
   '''
   ''' ' Display the TabControl in a Form
   ''' Me.Controls.Add(myTabControl)
   ''' myTabControl.BringToFront()
   '''
   ''' ' Hide the tab headers
   ''' myTabControl.HideTabheaders()
   '''
   ''' ' Show the tab headers with custom item size and filling to the right
   ''' myTabControl.ShowTabheaders(TabSizeMode.Normal, New Size(100, 50))
   ''' </code>
   ''' </example>
   ''' ---------------------------------------------------------------------------------------------------
   ''' <param name="tabControl">
   ''' The <see cref="TabControl"/> whose tab headers are to be shown.
   ''' </param>
   '''
   ''' <param name="sizeMode">
   ''' A value from <see cref="TabSizeMode"/> enumeration, that specifies the way that the control's tabs are sized.
   ''' </param>
   '''
   ''' <param name="itemSize">
   ''' Optional. The size of each tab header.
   ''' <para></para>
   ''' Default is <see cref="Size.Empty"/>, which is used to let the control automatically calculate the proper size
   ''' when <paramref name="sizeMode"/> is <see cref="TabSizeMode.Normal"/> or <see cref="TabSizeMode.FillToRight"/>.
   ''' </param>
   ''' ---------------------------------------------------------------------------------------------------
   <Extension>
   <DebuggerStepThrough>
   Public Sub ShowTabheaders(tabControl As TabControl, sizeMode As TabSizeMode, Optional itemSize As Size = Nothing)
       If itemSize = Nothing Then
           If sizeMode = TabSizeMode.Fixed Then
               Throw New ArgumentException("Value can't be null for fixed size mode.", paramName:=NameOf(itemSize))
           End If
           itemSize = Size.Empty
       End If
 
       With tabControl
           .SuspendLayout()
           .ItemSize = itemSize
           .SizeMode = sizeMode
           .ResumeLayout(performLayout:=True)
       End With
   End Sub
 
End Module

Modo de empleo utilizado en la imagen de demostración:
Código
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
   Me.TabControl1.HideTabheaders()
End Sub
 
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
   Me.TabControl1.ShowTabheaders(TabSizeMode.Normal)
End Sub

Eleкtro:
Les traigo una clase que he desarrollado, por nombre ToolStripCheckBox, cuyo nombre es autoexplicativo, pues se trata de un CheckBox que podemos usar en un componente ToolStrip y StatusStrip:





Código
#Region " Imports "
 
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Runtime.InteropServices
Imports System.Windows.Forms.Design
 
#End Region
 
#Region " ToolStripCheckBox "
 
''' <summary>
''' Represents a selectable <see cref="ToolStripItem"/> that when clicked, toggles a checkmark.
''' </summary>
''' <seealso cref="ToolStripControlHost"/>
<
   ClassInterface(ClassInterfaceType.AutoDispatch),
   ComVisible(True),
   DebuggerStepThrough,
   DefaultEvent(NameOf(ToolStripCheckBox.CheckedChanged)),
   DefaultProperty(NameOf(ToolStripCheckBox.Text)),
   Description("Represents a selectable ToolStripItem that when clicked, toggles a checkmark."),
   Designer("System.Windows.Forms.Design.ToolStripItemDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"),
   DesignerCategory(NameOf(DesignerCategoryAttribute.Generic)),
   DesignTimeVisible(False),
   DisplayName(NameOf(ToolStripCheckBox)),
   Localizable(True),
   ToolboxBitmap(GetType(CheckBox), "CheckBox.bmp"),
   ToolboxItem(False),
   ToolboxItemFilter("System.Windows.Forms", ToolboxItemFilterType.Allow),
   ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip Or ToolStripItemDesignerAvailability.StatusStrip)
>
Public Class ToolStripCheckBox : Inherits ToolStripControlHost
 
#Region " Properties "
 
   ''' <summary>
   ''' Gets the <see cref="CheckBox"/> control that is hosted by this <see cref="ToolStripCheckBox"/>.
   ''' </summary>
   <
       Browsable(True), EditorBrowsable(EditorBrowsableState.Advanced),
       DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
       Category("Hosted"), Description("The CheckBox control that is hosted by this control.")
   >
   Public Shadows ReadOnly Property Control As CheckBox
       Get
           Return DirectCast(MyBase.Control, CheckBox)
       End Get
   End Property
 
   ''' <summary>
   ''' Gets or sets a value indicating whether this <see cref="ToolStripCheckBox"/> is in the checked state.
   ''' </summary>
   '''
   ''' <returns>
   ''' <see langword="True"/> if checked; otherwise, <see langword="False"/>.
   ''' </returns>
   <
       Bindable(True), SettingsBindable(True),
       DefaultValue(False),
       RefreshProperties(RefreshProperties.All),
       Category("Appearance"), Description("Specifies whether this control is in the checked state.")
   >
   Public Property Checked As Boolean
       Get
           Return Me.Control.Checked
       End Get
       Set(value As Boolean)
           Me.Control.Checked = value
       End Set
   End Property
 
   ''' <summary>
   ''' Gets or sets the checked state of this <see cref="ToolStripCheckBox"/>.
   ''' </summary>
   '''
   ''' <returns>
   ''' One of the <see cref="System.Windows.Forms.CheckState"/> enumeration values.
   ''' <para></para>
   ''' The default value is <see cref="System.Windows.Forms.CheckState.Unchecked"/>.
   ''' </returns>
   '''
   ''' <exception cref="System.ComponentModel.InvalidEnumArgumentException">
   ''' The value assigned is not one of the <see cref="System.Windows.Forms.CheckState"/> enumeration values.
   ''' </exception>
   <
       Bindable(True),
       DefaultValue(CheckState.Unchecked),
       RefreshProperties(RefreshProperties.All),
       Category("Appearance"), Description("Specifies the checked state of this control.")
   >
   Public Property CheckState As CheckState
       Get
           Return Me.Control.CheckState
       End Get
       Set(value As CheckState)
           Me.Control.CheckState = value
       End Set
   End Property
 
   ''' <summary>
   ''' Gets or sets a value indicating whether this <see cref="ToolStripCheckBox"/>
   ''' will allow three check states rather than two.
   ''' </summary>
   '''
   ''' <remarks>
   ''' If the <see cref="ToolStripCheckBox.ThreeState"/> property is set to <see langword="False"/>,
   ''' the <see cref="ToolStripCheckBox.CheckState"/> property value can only be set to
   ''' the <see cref="System.Windows.Forms.CheckState.Indeterminate"/> value in code,
   ''' and not by user interaction doing click on the control.
   ''' </remarks>
   '''
   ''' <returns>
   ''' <see langword="True"/> if this <see cref="ToolStripCheckBox"/>
   ''' is able to display three check states; otherwise, <see langword="False"/>.
   ''' <para></para>
   ''' The default value is <see langword="False"/>.
   ''' </returns>
   <
       DefaultValue(False),
       Category("Behavior"), Description("Specifies whether this control will allow three check states rather than two.")
   >
   Public Property ThreeState As Boolean
       Get
           Return Me.Control.ThreeState
       End Get
       Set(value As Boolean)
           Me.Control.ThreeState = value
       End Set
   End Property
 
#End Region
 
#Region " Events "
 
   ''' <summary>
   ''' Occurs whenever the <see cref="ToolStripCheckBox.Checked"/> property is changed.
   ''' </summary>
   Public Event CheckedChanged As EventHandler
 
   ''' <summary>
   ''' Occurs whenever the <see cref="ToolStripCheckBox.CheckState"/> property is changed.
   ''' </summary>
   Public Event CheckStateChanged As EventHandler
 
#End Region
 
#Region " Constructors "
 
   ''' <summary>
   ''' Initializes a new instance of the <see cref="ToolStripCheckBox"/> class.
   ''' </summary>
   Public Sub New()
 
       MyBase.New(New CheckBox())
       Me.Control.BackColor = Color.Transparent
   End Sub
 
#End Region
 
#Region " Event Invocators "
 
   ''' <summary>
   ''' Raises the <see cref="ToolStripCheckBox.CheckedChanged"/> event.
   ''' </summary>
   '''
   ''' <param name="sender">
   ''' The source of the event.
   ''' </param>
   '''
   ''' <param name="e">
   ''' The <see cref="EventArgs"/> instance containing the event data.
   ''' </param>
   Private Sub OnCheckedChanged(sender As Object, e As EventArgs)
       If Me.CheckedChangedEvent IsNot Nothing Then
           RaiseEvent CheckedChanged(Me, e)
       End If
   End Sub
 
   ''' <summary>
   ''' Raises the <see cref="ToolStripCheckBox.CheckStateChanged"/> event.
   ''' </summary>
   '''
   ''' <param name="sender">
   ''' The source of the event.
   ''' </param>
   '''
   ''' <param name="e">
   ''' The <see cref="EventArgs"/> instance containing the event data.
   ''' </param>
   Private Sub OnCheckStateChanged(sender As Object, e As EventArgs)
       If Me.CheckStateChangedEvent IsNot Nothing Then
           RaiseEvent CheckStateChanged(Me, e)
       End If
   End Sub
 
#End Region
 
#Region " Event Invocators (Overriden) "
 
   ''' <summary>
   ''' Subscribes events from the hosted control
   ''' </summary>
   '''
   ''' <param name="control">
   ''' The control from which to subscribe events.
   ''' </param>
   Protected Overrides Sub OnSubscribeControlEvents(control As Control)
       MyBase.OnSubscribeControlEvents(control)
       AddHandler DirectCast(control, CheckBox).CheckedChanged, AddressOf Me.OnCheckedChanged
   End Sub
 
   ''' <summary>
   ''' Unsubscribes events from the hosted control
   ''' </summary>
   '''
   ''' <param name="control">
   ''' The control from which to unsubscribe events.
   ''' </param>
   Protected Overrides Sub OnUnsubscribeControlEvents(control As Control)
       MyBase.OnUnsubscribeControlEvents(control)
       RemoveHandler DirectCast(control, CheckBox).CheckedChanged, AddressOf Me.OnCheckedChanged
   End Sub
 
   ''' <summary>
   ''' Raises the <see cref="Windows.Forms.Control.ParentChanged"/> event.
   ''' </summary>
   '''
   ''' <param name="oldParent">
   ''' The original parent of the item.
   ''' </param>
   '''
   ''' <param name="newParent">
   ''' The new parent of the item.
   ''' </param>
   Protected Overrides Sub OnParentChanged(oldParent As ToolStrip, newParent As ToolStrip)
       MyBase.OnParentChanged(oldParent, newParent)
   End Sub
 
   ''' <summary>
   ''' Raises the <see cref="ToolStripItem.OwnerChanged"/> event.
   ''' </summary>
   '''
   ''' <param name="e">
   ''' The <see cref="EventArgs"/> instance containing the event data.
   ''' </param>
   Protected Overrides Sub OnOwnerChanged(e As EventArgs)
       MyBase.OnOwnerChanged(e)
   End Sub
 
#End Region
 
End Class
 
#End Region

Eleкtro:
Un simple validador de rutas de archivos y directorios para operaciones de arrastrar y soltar (Drag&Drop) sobre un control, que nos permite indicar si se debe permitir arrastrar múltiples rutas, y opcionalmente la extensión de los archivos que se deben permitir.

El método de validación es sencillo de adaptar a otros escenarios, y nos puede ahorrar mucho tiempo repitiendo código para este tipo de validaciones.

Código
''' <summary>
''' Specifies the type of paths that can be dragged in a drag&amp;drop operation.
''' </summary>
Public Enum PathDragType
 
       ''' <summary>
       ''' Only files can be dragged.
       ''' </summary>
       Files
 
       ''' <summary>
       ''' Only directories can be dragged.
       ''' </summary>
       Directories
 
       ''' <summary>
       ''' Both files and directories can be dragged.
       ''' </summary>
       Any
 
End Enum
 
''' <summary>
''' Validates the <see cref="IDataObject"/> for a file or directory drag operation,
''' and returns the appropriate <see cref="DragDropEffects"/>.
''' <para></para>
''' This function should be called on the <see cref="Control.DragEnter"/> event handler of a control,
''' to assign its return value for the <see cref="DragEventArgs.Effect"/> property.
''' </summary>
'''
''' <example> This is a code example that shows how to validate a drag operation for a single file matching the specified file extensions.
''' <code language="VB">
''' Private Sub TextBox1_DragEnter(sender As Object, e As DragEventArgs) Handles TextBox1.DragEnter
'''
'''     Dim allowedFileExtensions As String() = {"avi", "mkv", "mp4"}
'''     e.Effect = ValidatePathDrag(e.Data, PathDragType.Files, allowMultiplePaths:=False, allowedFileExtensions)
''' End Sub
'''
''' Private Sub TextBox1_DragDrop(sender As Object, e As DragEventArgs) Handles TextBox1.DragDrop
'''
'''     If e.Data.GetDataPresent(DataFormats.FileDrop) AndAlso e.Effect = DragDropEffects.Copy Then
'''         Dim singleFilePath As String = DirectCast(e.Data.GetData(DataFormats.FileDrop), String()).SingleOrDefault()
'''
'''         Dim tb As TextBox = DirectCast(sender, TextBox)
'''         tb.Text = singleFilePath
'''     End If
''' End Sub
''' </code>
''' </example>
'''
''' <param name="data">
''' The source <see cref="IDataObject"/> object to validate,
''' typically the object retrieved from <see cref="DragEventArgs.Data"/> property.
''' </param>
'''
''' <param name="allowedDragType">
''' A <see cref="PathDragType"/> value that indicates the
''' type of paths allowed for the drag operation (files, directories, or any).
''' </param>
'''
''' <param name="allowMultiplePaths">
''' A <see cref="Boolean"/> value indicating whether dragging multiple paths are allowed for the drag operation.
''' <para></para>
''' If this value is <see langword="False"/> and the <paramref name="data"/> object
''' contains multiple paths, <see cref="DragDropEffects.None"/> is returned.
''' </param>
'''
''' <param name="allowedFileExtensions">
''' Optional. An array of file extensions to allow in a file drag operation. By default, all file extensions are allowed.
''' <para></para>
''' If any of the file paths contained in the <paramref name="data"/> object does not match
''' the specified allowed file extensions, <see cref="DragDropEffects.None"/> is returned.
''' <para></para>
''' This parameter has no effect for directories contained in the <paramref name="data"/> object.
''' </param>
'''
''' <returns>
''' Returns <see cref="DragDropEffects.Copy"/> If the drag validation was successful;
''' otherwise, returns <see cref="DragDropEffects.None"/>.
''' </returns>
<DebuggerStepThrough>
Public Shared Function ValidatePathDrag(data As IDataObject,
                                       allowedDragType As PathDragType,
                                       allowMultiplePaths As Boolean,
                                       ParamArray allowedFileExtensions As String()) As DragDropEffects
 
   Dim dataObject As DataObject = DirectCast(data, DataObject)
   If dataObject.ContainsFileDropList() Then
       Dim filePathList As New List(Of String)
       Dim pathList As StringCollection = dataObject.GetFileDropList()
       Dim pathListlength As Integer = pathList.Count
 
       ' Single/multiple path validation.
       If (Not allowMultiplePaths AndAlso pathListlength > 1) Then
           Return DragDropEffects.None
       End If
 
       Select Case allowedDragType
 
           ' Fails if path list contains any file.
           Case PathDragType.Directories
               For Each path As String In pathList
                   If File.Exists(path) Then
                       Return DragDropEffects.None
                   End If
               Next
 
           ' Fails if path list contains any directory.
           Case PathDragType.Files, PathDragType.Any
               For Each path As String In pathList
                   If Directory.Exists(path) Then
                       Return DragDropEffects.None
                   End If
                   ' Build the list of file paths, excluding any directory from the path list.
                   filePathList.Add(path)
               Next
 
       End Select
 
       If allowedFileExtensions?.Any() AndAlso filePathList.Any() Then
           ' Trims the dot and white spaces to ensure that malformed file extension strings are corrected (eg. " .jpg"  -> "jpg").
           Dim allowedFileExtensionsLower As IEnumerable(Of String) =
                       From ext As String In allowedFileExtensions Select ext.TrimStart({"."c, " "c}).ToLower()
 
           For Each filePath As String In filePathList
               ' Trims the dot from file extension strings (eg. ".jpg" -> "jpg").
               Dim fileExtLower As String = IO.Path.GetExtension(filePath).TrimStart("."c).ToLower()
               If Not allowedFileExtensionsLower.Contains(fileExtLower) Then
                   Return DragDropEffects.None
               End If
           Next
       End If
 
       Return DragDropEffects.Copy
   End If
 
   Return DragDropEffects.None
End Function
 


Aquí muestro un ejemplo de uso, donde establezco que solamente se acepte arrastrar un archivo, y siempre y cuando ese archivo tenga la extensión avi, mp4 o mkv:

Código
Private Sub TextBox1_DragEnter(sender As Object, e As DragEventArgs) Handles TextBox1.DragEnter
   Dim allowedFileExtensions As String() = {"avi", "mkv", "mp4"}
   e.Effect = ValidatePathDrag(e.Data, PathDragType.Files, allowMultiplePaths:=False, allowedFileExtensions)
End Sub
 
Private Sub TextBox1_DragDrop(sender As Object, e As DragEventArgs) Handles TextBox1.DragDrop
   Dim singleFilePath As String = DirectCast(e.Data.GetData(DataFormats.FileDrop), String()).Single()
 
   Dim tb As TextBox = DirectCast(sender, TextBox)
   tb.Text = singleFilePath
End Sub

Eleкtro:
Dos métodos de extensión para iterar todos los items (ToolStripItem) de un control de tipo ToolStrip, StatusStrip, MenuStrip o ContextMenuStrip, opcionalmente de forma recursiva (sin recursión de método), y llevar a cabo una acción específica sobre cada item:

Código
' ***********************************************************************
' Author   : ElektroStudios
' Modified : 12-April-2024
' ***********************************************************************
 
#Region " Public Members Summary "
 
' ToolStrip.ForEachItem(Boolean, Action(Of ToolStripItem))
' ToolStrip.ForEachItem(Of T As ToolStripItem)(Boolean, Action(Of T))
 
#End Region
 
#Region " Option Statements "
 
Option Strict On
Option Explicit On
Option Infer Off
 
#End Region
 
#Region " Imports "
 
Imports System.Collections.Generic
Imports System.Linq
Imports System.Runtime.CompilerServices
Imports System.Windows.Forms
 
#If Not NETCOREAPP Then
Imports DevCase.ProjectMigration
#Else
Imports System.Runtime.Versioning
#End If
#End Region
 
#Region " ToolStrip Extensions "
 
' ReSharper disable once CheckNamespace
 
Namespace DevCase.Extensions.ToolStripExtensions
 
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Provides custom extension methods to use with <see cref="System.Windows.Forms.ToolStrip"/> class.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<HideModuleName>
Public Module ToolStripExtensions
 
#Region " Public Extension Methods "
 
''' ---------------------------------------------------------------------------------------------------
''' <summary>
''' Iterates through all the items of the specified type within the source <see cref="ToolStrip"/> control,
''' optionally recursively, and performs the specified action on each item.
''' </summary>
''' ---------------------------------------------------------------------------------------------------
''' <param name="toolStrip">
''' The <see cref="ToolStrip"/> control whose items are to be iterated.
''' </param>
'''
''' <param name="recursive">
''' <see langword="True"/> to iterate recursively through all items
''' (i.e., iterate the child items of child items); otherwise, <see langword="False"/>.
''' </param>
'''
''' <param name="action">
''' The action to perform on each item.
''' </param>
''' ---------------------------------------------------------------------------------------------------
<Extension>
<DebuggerStepThrough>
<EditorBrowsable(EditorBrowsableState.Always)>
Public Sub ForEachItem(toolStrip As ToolStrip, recursive As Boolean, action As Action(Of ToolStripItem))
   ToolStripExtensions.ForEachItem(Of ToolStripItem)(toolStrip, recursive, action)
End Sub
 
''' ---------------------------------------------------------------------------------------------------
''' <summary>
''' Iterates through all the items of the specified type within the source <see cref="ToolStrip"/> control,
''' optionally recursively, and performs the specified action on each item.
''' </summary>
''' ---------------------------------------------------------------------------------------------------
''' <typeparam name="T">
''' The type of items to iterate through.
''' </typeparam>
'''
''' <param name="toolStrip">
''' The <see cref="ToolStrip"/> control whose items are to be iterated.
''' </param>
'''
''' <param name="recursive">
''' <see langword="True"/> to iterate recursively through all items
''' (i.e., iterate the child items of child items); otherwise, <see langword="False"/>.
''' </param>
'''
''' <param name="action">
''' The action to perform on each item.
''' </param>
''' ---------------------------------------------------------------------------------------------------
<Extension>
<DebuggerStepThrough>
<EditorBrowsable(EditorBrowsableState.Always)>
Public Sub ForEachItem(Of T As ToolStripItem)(toolStrip As ToolStrip, recursive As Boolean, action As Action(Of T))
   If action Is Nothing Then
       Throw New ArgumentNullException(paramName:=NameOf(action), "Action cannot be null.")
   End If
 
   Dim queue As New Queue(Of ToolStripItem)
 
   ' First level items iteration.
   For Each item As ToolStripItem In toolStrip.Items
       If recursive Then
           queue.Enqueue(item)
       Else
           If TypeOf item Is T Then
               action.Invoke(DirectCast(item, T))
           End If
       End If
   Next item
 
   ' Recursive items iteration.
   While queue.Any()
       Dim currentItem As ToolStripItem = queue.Dequeue()
       If TypeOf currentItem Is T Then
           action.Invoke(DirectCast(currentItem, T))
       End If
 
       If TypeOf currentItem Is ToolStripDropDownItem Then
           Dim dropDownItem As ToolStripDropDownItem = DirectCast(currentItem, ToolStripDropDownItem)
           For Each subItem As ToolStripItem In dropDownItem.DropDownItems
               queue.Enqueue(subItem)
           Next subItem
       End If
   End While
End Sub
 
#End Region
 
End Module
 
End Namespace
 
#End Region


Otros dos métodos para iterar los controles hijo de un control padre (el control padre puede ser de tipo Form, ContainerControl, Control, etc), opcionalmente de forma recursiva (sin recursión de método), y poder llevar a cabo una acción específica sobre cada control:

Código
<HideModuleName>
public module ControlExtensions
 
   ''' ---------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Iterates through all controls within a parent <see cref="Control"/>,
   ''' optionally recursively, and performs the specified action on each control.
   ''' </summary>
   ''' ---------------------------------------------------------------------------------------------------
   ''' <param name="parentControl">
   ''' The parent <see cref="Control"/> whose child controls are to be iterated.
   ''' </param>
   '''
   ''' <param name="recursive">
   ''' <see langword="True"/> to iterate recursively through all child controls
   ''' (i.e., iterate the child controls of child controls); otherwise, <see langword="False"/>.
   ''' </param>
   '''
   ''' <param name="action">
   ''' The action to perform on each control.
   ''' </param>
   ''' ---------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   <Extension>
   <EditorBrowsable(EditorBrowsableState.Always)>
   Public Sub ForEachControl(parentControl As Control, recursive As Boolean, action As Action(Of Control))
       ControlExtensions.ForEachControl(Of Control)(parentControl, recursive, action)
   End Sub
 
   ''' ---------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Iterates through all controls of the specified type within a parent <see cref="Control"/>,
   ''' optionally recursively, and performs the specified action on each control.
   ''' </summary>
   ''' ---------------------------------------------------------------------------------------------------
   ''' <typeparam name="T">
   ''' The type of child controls to iterate through.
   ''' </typeparam>
   '''
   ''' <param name="parentControl">
   ''' The parent <see cref="Control"/> whose child controls are to be iterated.
   ''' </param>
   '''
   ''' <param name="recursive">
   ''' <see langword="True"/> to iterate recursively through all child controls
   ''' (i.e., iterate the child controls of child controls); otherwise, <see langword="False"/>.
   ''' </param>
   '''
   ''' <param name="action">
   ''' The action to perform on each control.
   ''' </param>
   ''' ---------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   <Extension>
   <EditorBrowsable(EditorBrowsableState.Always)>
   Public Sub ForEachControl(Of T As Control)(parentControl As Control, recursive As Boolean, action As Action(Of T))
 
       If TypeOf parentControl Is ToolStrip Then
           Throw New InvalidOperationException($"Not allowed. Please use method {NameOf(ToolStripExtensions.ForEachItem)} to iterate items of a {NameOf(ToolStrip)}, {NameOf(StatusStrip)}, {NameOf(MenuStrip)} or {NameOf(Control.ContextMenuStrip)} controls.")
       End If
 
       If action Is Nothing Then
           Throw New ArgumentNullException(paramName:=NameOf(action), "Action cannot be null.")
       End If
 
       Dim queue As New Queue(Of Control)
 
       ' First level items iteration.
       For Each control As Control In parentControl.Controls
           If recursive Then
               queue.Enqueue(control)
           Else
               If TypeOf control Is T Then
                   action.Invoke(DirectCast(control, T))
               End If
           End If
       Next control
 
       ' Recursive items iteration.
       While queue.Any()
           Dim currentControl As Control = queue.Dequeue()
           If TypeOf currentControl Is T Then
               action.Invoke(DirectCast(currentControl, T))
           End If
 
           For Each childControl As Control In currentControl.Controls
               queue.Enqueue(childControl)
           Next childControl
       End While
 
   End Sub
 
end module

Eleкtro:
El siguiente método sirve para aplicar, de forma automatizada, y recursivamente, los recursos aplicables de localización para un Form específico, o para todos los Forms visibles de la aplicación actual.

En otras palabras, el siguiente método sirve para automatizar un cambio de idioma en nuestra aplicación, y tan solo necesitando una línea de código para llamar a dicho método...



He tenido que desarrollar este método, por que todas las alternativas que hay disponibles por Internet son muy básicas e ineficientes, ya que se limitan a iterar los controles y controles hijo, mientras que mi implementación además también itera los menús y sus items de forma recursiva, y los componentes de un form (como un NotifyIcon).


Ejemplos de uso:

Código
' Aplica recursos de localización a un form específico
Dim form As Form = Me
Dim cultureName As String = "es-ES"
ApplyCultureResources(form, cultureName)

Código
' Aplica recursos de localización a todos los forms de la aplicación
Dim cultureName As String = "es-ES"
ApplyCultureResources(cultureName)

Salida de depuración (ejemplo limitado):

Cambio de idioma a Inglés:
Código:

Culture: English (en), Component: Form1                 , Text: My Form
Culture: English (en), Component: Button1               , Text: My Button
Culture: English (en), Component: ToolStrip1            , Text: (null)
Culture: English (en), Component: ToolStripStatusLabel1 , Text: Testing
Culture: English (en), Component: MenuStrip1            , Text: (null)
Culture: English (en), Component: ToolStripMenuItem1    , Text: One
Culture: English (en), Component: ToolStripMenuItem2    , Text: Two
Culture: English (en), Component: TabControl1           , Text: (null)
Culture: English (en), Component: TabPage1              , Text: Page 1
Culture: English (en), Component: TabPage2              , Text: Page 2
Culture: English (en), Component: NotifyIcon1           , Text: Icon

Cambio de idioma a Español:
Código:

Culture: Spanish (es), Component: Form1                 , Text: Mi Form
Culture: Spanish (es), Component: Button1               , Text: Mi Botón
Culture: Spanish (es), Component: ToolStrip1            , Text: (null)
Culture: Spanish (es), Component: ToolStripStatusLabel1 , Text: Probando
Culture: Spanish (es), Component: MenuStrip1            , Text: (null)
Culture: Spanish (es), Component: ToolStripMenuItem1    , Text: Uno
Culture: Spanish (es), Component: ToolStripMenuItem2    , Text: Dos
Culture: Spanish (es), Component: TabControl1           , Text: (null)
Culture: Spanish (es), Component: TabPage1              , Text: Página 1
Culture: Spanish (es), Component: TabPage2              , Text: Página 2
Culture: Spanish (es), Component: NotifyIcon1           , Text: Icono


IMPORTANTE: el siguiente método depende de los métodos de extensión ForEachControl y ForEachItem que compartí en el post anterior de este hilo:

Cita de: https://foro.elhacker.net/net_c_vbnet_asp/libreria_de_snippets_para_vbnet_compartan_aqui_sus_snippets-t378770.0.html;msg2278467#msg2278467

Dos métodos de extensión para iterar todos los items (ToolStripItem) de un control...

Otros dos métodos para iterar los controles hijo de un control...

Y también depende de este otro método de extensión:

Código
''' <summary>
''' Provides extension methods for the <see cref="WinForms.IContainerControl"/> interface.
''' </summary>
<HideModuleName>
Public Module IContainerControlExtensions
 
 
   ''' <summary>
   ''' Gets the underlying <see cref="System.ComponentModel.ComponentCollection"/> collection
   ''' of the source <see cref="IContainerControl"/>.
   ''' </summary>
   '''
   ''' <param name="container">
   ''' The source <see cref="IContainerControl"/>.
   ''' </param>
   '''
   ''' <returns>
   ''' The underlying <see cref="System.ComponentModel.ComponentCollection"/> collection
   ''' of the source <see cref="IContainerControl"/>.
   ''' </returns>
   <DebuggerStepThrough>
   <Extension>
   <EditorBrowsable(EditorBrowsableState.Always)>
   Public Function GetComponentCollection(container As IContainerControl) As ComponentCollection
       Dim type As Type = container.GetType()
       Dim componentsField As FieldInfo = type.GetField("components", BindingFlags.NonPublic Or BindingFlags.Instance)
 
       If componentsField Is Nothing Then
           Throw New InvalidOperationException("""components"" field was not found through Reflection.")
       End If
 
       Dim containerComponents As IContainer = TryCast(componentsField.GetValue(container), IContainer)
       Return containerComponents?.Components
   End Function
 
End Module


El código:

Código
''' <summary>
''' This method sets the current UI culture to the specified culture name,
''' then applies culture-specific resources to the specified <see cref="Form"/>,
''' to its controls and child controls, including menus and their items, and
''' the components in the form's <see cref="ComponentCollection"/>, recursively.
''' </summary>
'''
''' <example> This is a code example.
''' <code language="VB">
''' Dim form As Form = Me
''' Dim cultureName As String = "es-ES"
''' ApplyCultureResources(form, cultureName)
''' </code>
''' </example>
'''
''' <param name="form">
''' The form to apply resources to.
''' </param>
'''
''' <param name="cultureName">
''' The culture name of the resources to apply.
''' </param>
Public Shared Sub ApplyCultureResources(form As Form, cultureName As String)
 
   Dim culture As CultureInfo = CultureInfo.GetCultureInfo(cultureName)
#If Not NETCOREAPP Then
           My.Application.ChangeUICulture(cultureName)
#Else
           Thread.CurrentThread.CurrentUICulture = culture
#End If
 
   Dim resources As New ComponentResourceManager(form.GetType())
 
   ' Action delegate that applies resources to an IComponent.
   Dim applyResources As Action(Of IComponent, String) =
       Sub(component As IComponent, name As String)
           If String.IsNullOrEmpty(name) Then
               ' Not valid to apply localization resources.
               Exit Sub
           Else
               resources.ApplyResources(component, name, culture)
           End If
 
           ' Applies resources to the items and subitems of a ToolStrip component, recursively.
           If TypeOf component Is ToolStrip Then
               Dim ts As ToolStrip = DirectCast(component, ToolStrip)
               ToolStripExtensions.ForEachItem(ts, recursive:=True, Sub(item) applyResources(item, item.Name))
           End If
 
#If DEBUG Then ' Prints debug information.
           ' Flags to retrieve the "Text" property of a component.
           Const textPropBindingFlags As BindingFlags =
               BindingFlags.Instance Or BindingFlags.Static Or
               BindingFlags.Public Or BindingFlags.NonPublic
 
           Dim textProp As PropertyInfo =
               (From prop As PropertyInfo In component.GetType().GetProperties(textPropBindingFlags)
                Where prop.PropertyType Is GetType(String) AndAlso
                      prop.Name.Equals("Text", StringComparison.OrdinalIgnoreCase)
               ).SingleOrDefault()
 
           Dim text As String = DirectCast(textProp?.GetValue(component), String)
           If String.IsNullOrEmpty(text) Then
               text = "(null)"
           End If
           Debug.WriteLine($"Culture: {culture.EnglishName} ({culture.Name}), Component: {name,-40}, Text: {text}")
#End If
       End Sub
 
   ' Apply resources to the form.
   applyResources(form, form.Name)
 
   ' Apply resources to the controls hosted in the form, recursively.
   FormExtensions.ForEachControl(form, recursive:=True, Sub(ctrl) applyResources(ctrl, ctrl.Name))
 
   ' Apply resources to the components hosted in the ComponentCollection of the form.
   Dim components As ComponentCollection = IContainerControlExtensions.GetComponentCollection(form)
   If components IsNot Nothing Then
       ' Flags to retrieve the "Name" property of a component.
       Const namePropBindingFlags As BindingFlags =
           BindingFlags.Instance Or BindingFlags.Static Or
           BindingFlags.Public Or BindingFlags.NonPublic
 
       For Each component As IComponent In components
           Dim nameProp As PropertyInfo =
                 (From prop As PropertyInfo In component.GetType().GetProperties(namePropBindingFlags)
                  Where prop.PropertyType Is GetType(String) AndAlso
                        prop.Name.Equals("Name", StringComparison.OrdinalIgnoreCase)
                 ).SingleOrDefault()
 
           Dim name As String = DirectCast(nameProp?.GetValue(component), String)
           applyResources(component, name)
       Next component
   End If
 
   ' This code finds and applies resources to component fields declared at the form level
   ' (including those in the auto-generated code of the form designer) that doesn't have
   ' defined a "Name" property (such as NotifyIcon, ColorDialog, OpenFileDialog, etc).
   Const fieldsBindingFlags As BindingFlags =
       BindingFlags.Instance Or BindingFlags.DeclaredOnly Or BindingFlags.Static Or
       BindingFlags.Public Or BindingFlags.NonPublic
 
   Dim fields As IEnumerable(Of FieldInfo) =
               From field As FieldInfo In form.GetType().GetFields(fieldsBindingFlags)
               Where GetType(IComponent).IsAssignableFrom(field.FieldType) AndAlso
                 Not GetType(Control).IsAssignableFrom(field.FieldType) AndAlso
                 Not GetType(ToolStripItem).IsAssignableFrom(field.FieldType)
 
   For Each field As FieldInfo In fields
       Dim component As IComponent = DirectCast(field.GetValue(form), IComponent)
       Dim name As String = field.Name.TrimStart("_"c) ' E.g.: "_NotifyIcon1" -> "NotifyIcon1"
       applyResources(component, name)
   Next field
 
End Sub

Código
''' <summary>
''' This method sets the current UI culture to the specified culture name,
''' then applies culture-specific resources to the open forms of the current application,
''' to its controls and child controls, including menus and their items, and
''' the components in the form's <see cref="ComponentCollection"/>, recursively.
''' </summary>
'''
''' <example> This is a code example.
''' <code language="VB">
''' Dim cultureName As String = "es-ES"
''' ApplyCultureResources(cultureName)
''' </code>
''' </example>
'''
''' <param name="cultureName">
''' The culture name of the resources to apply.
''' </param>
Public Shared Sub ApplyCultureResources(cultureName As String)
   For Each form As Form In System.Windows.Forms.Application.OpenForms
       ApplyCultureResources(form, cultureName)
   Next form
End Sub

Navegación

[0] Índice de Mensajes

[#] Página Siguiente

[*] Página Anterior