using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsControls
{
    /// <summary>
    /// Este ejemplo muestra el uso de controles contenedores.
    /// Ya que cada contenedor sólo informa de los controles
    /// de primer nivel que contiene, es necesario una función 
    /// recursiva para recorrer la totalidad de controles del formulario.
    /// Tener en cuenta que la clase form, está repartida en dos archivos
    /// físicos diferentes gracias a la nueva característica incorporada
    /// en .NET 2.0 denominada Partial class.
    /// En este archivo, (cuyo nombre es el nombre de la clase, con extensión .cs
    /// (para c# y .vb para VB.NET) se encuentra sólamente el constructor de la
    /// clase y el código que hace funcionar al ejemplo.
    /// Todo el código que escribe el diseñador de formularios, está separado en un 
    /// archivo físico diferente (cuyo nombre se conforma de [NombreClase].Designer.cs 
    /// o .vb para VB.NET.
    /// </summary>
    public partial class Form1 : Form
    {
        StringBuilder informe = new StringBuilder();

        public Form1()
        {
            InitializeComponent();
        }

        private void Salir_Click(object sender, EventArgs e)
        {
            this.Close();
            this.Dispose();
        }

        private void MenuVerInforme_Click(object sender, EventArgs e)
        {
            VisualizaInforme();
        }

        private void VerInforme_Click(object sender, EventArgs e)
        {
            VisualizaInforme();
        }

        private void VisualizaInforme()
        {
            InformeFormulario();

            ArmaInforme(this.Controls);

            MessageBox.Show(informe.ToString(), "Detalle de controles del formulario", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        /// <summary>
        /// Arma el encabezado del informe con los datos del formulario.
        /// </summary>
        private void InformeFormulario()
        {
            informe.Append("Contenedor -> ");
            informe.Append(this.Name);
            informe.Append(" - Contiene: ");
            informe.Append(this.Controls.Count.ToString());
            informe.Append(" controles");
            informe.Append("\n");
        }

        /// <summary>
        /// Método recursivo. Utiliza un string builder para armar el informe 
        /// para un uso más optimo de la memoria, ya que el mismo se arma en 
        /// base a concatenación de cadenas de caracteres.
        /// </summary>
        /// <param name="controles"></param>
        private void ArmaInforme(Control.ControlCollection controles)
        {
            foreach (Control control in controles)
            {
                if (control.HasChildren)
                {
                    informe.Append("Contenedor -> ");
                    informe.Append(control.Name);
                    informe.Append(" - Contiene: ");
                    informe.Append(control.Controls.Count.ToString());
                    informe.Append(" controles");
                    informe.Append("\n");
                    ArmaInforme(control.Controls);
                }
                else
                {
                    informe.Append("Control Hijo -> ");
                    informe.Append(control.Name);
                    informe.Append(" - Es hijo de: ");
                    informe.Append(control.Parent.Name);
                    informe.Append("\n");
                }
            }
        }

    }
}