-5

I have the problem, that:

TabPage tab = new TabPage();
[...]
for (int i = 0; i < tab.Controls.Count; i++)
{
   Debug.WriteLine(i + " - " + tab.Controls[i].Name + " - " + tab.Controls[i].Text);
}

has obviously not the same result than:

TabPage tab = new TabPage();
[...]
int j = 0;
foreach (Control ctl in tab.Controls)
{
    Debug.WriteLine(j + " - " + ctl.Name + " - " + ctl.Text);
    j++;
}

The for loop has in my case as result 53 items (Count shows 53) but the foreach loop has as result only 27 items.

I cannot understand this. What could be the reason?

Adelphos
  • 83
  • 7
  • 1
    You should show the debug output as well. – Jonathon Reinhart Jul 23 '15 at 12:18
  • 3
    That wouldn't compile, what's that `int j++` doing there? Surely that should just be `j++`? Also, is this all the code you're using to reproduce the issue? 27 * 2 = 54, which feels a bit fishy to me. – Yannick Meeus Jul 23 '15 at 12:24
  • There's nothing special in `ControlCollection.Count` or in [`ControlCollection.GetEnumerator`](http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Control.cs,10afde280b1d4508). So i doubt that this issue is reproducible. Something else causes it. Maybe a forgotten `--j`. – Tim Schmelter Jul 23 '15 at 12:28
  • 1
    @TimSchmelter, yeah, trying to reproduce here but honestly, I feel like we're missing part of the story, some dodgy double incrementation of j somewhere or the like. – Yannick Meeus Jul 23 '15 at 12:29
  • I changed now wrong **int j++;** to correct **j++;** in foreach in the question, too, for this was not the problem... – Adelphos Jul 24 '15 at 09:57

1 Answers1

0

I could solve the problem now by my own:

The second sourcecode wasn't like posted it was like this:

TabPage tab = new TabPage();
[...]
int j = 0;
foreach (Control ctl in tab.Controls)
{
    Debug.WriteLine(j + " - " + ctl.Name + " - " + ctl.Text);
    tab2.Controls.Add(ctl);
    j++;
}

=> So I moved accidental my Control during foreach loop, but I want only clone it and this is the answer how to do it: Clone Controls - C# (Winform)

Now I fixed it like that:

foreach (Control ctl in tab1.Controls)
{
    try
    {
        if (ctl != null)
        {
            object obj_clone = CloneObject(ctl);
            if (obj_clone != null && obj_clone is Control)
            {
                Control ctl_clone = (Control)CloneObject(ctl);
                tab2.Controls.Add(ctl_clone);
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception: " + ex.Message + " - TargetSite:" + ex.TargetSite + " - Source: " + ex.Source + " - InnerException: " + ex.InnerException.Message.ToString());
    }
}

private Object CloneObject(Object obj)
{
    var typ = obj.GetType();
    var obj_clone = CreateInstanceOfType(typ);
    PropertyInfo[] controlProperties = typ.GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (PropertyInfo propInfo in controlProperties)
    {
        if (propInfo.CanWrite && propInfo.Name != "WindowTarget")
        {
            try
            {
                if (propInfo.PropertyType.IsValueType || propInfo.PropertyType.IsEnum || propInfo.PropertyType.Equals(typeof(System.String)))
                {
                    propInfo.SetValue(obj_clone, propInfo.GetValue(obj));
                }
                else
                {
                    object value = propInfo.GetValue(obj);
                    if (value == null)
                        propInfo.SetValue(obj_clone, null);
                    else
                        propInfo.SetValue(obj_clone, CloneObject(value));
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception: " + ex.Message + " - TargetSite:" + ex.TargetSite + " - Source: " + ex.Source + " - InnerException: " + ex.InnerException.Message.ToString());
            }
        }
    }
    return (Object)obj_clone;
}

public object CreateInstanceOfType(Type type)
{
    // First make an instance of the type.
    object instance = null;

    // If there is an empty constructor, call that.
    if (type.GetConstructor(Type.EmptyTypes) != null)
        instance = Activator.CreateInstance(type);
    else
    {
        // Otherwise get the first available constructor and fill in some default values.
        // (we are trying to set all properties anyway so it shouldn't be much of a problem).
        ConstructorInfo ci = type.GetConstructors()[0];
        ParameterInfo[] parameters = ci.GetParameters();

        object[] ciParams = new object[parameters.Length];

        for (int i = 0; i < parameters.Length; i++)
        {
            if (parameters[i].DefaultValue != null)
            {
                ciParams[i] = parameters[i].DefaultValue;
                continue;
            }

            Type paramType = parameters[i].ParameterType;
            ciParams[i] = CreateInstanceOfType(paramType);
        }

        instance = ci.Invoke(ciParams);
    }

    return instance;
}
Community
  • 1
  • 1
Adelphos
  • 83
  • 7