serenaa
serenaa

Reputation: 11

C# + bindingsource value gets overwritten

This is my requirement: I have a datagridview which should be populated with employee shift data from shift details which is available in sch.shift_detailsList(entity model-shift). For eg: shift for 1 week(nov 1 to nov 7) is saved in sch.shift_detailsList.So in the datagridview if the weekcount=2(ie shift to be saved for 2 weeks, ie cycledays=7*2 -1=13) , the bindingsource1(for the datagridview) should be populated with shift for 2 weeks, ie if start date given as nov1, then the shift details in sch.shift_detailsList should be repeated for the 2nd week also. So, when the loop finishes the 1st week and then i=7, and again it should start from first item of sch.shift_detailsList and the 8th entry in bindingSource1 (8) date should be nov 8th .but my issue is that now, the date in bindingSource1 (0) and sch.shift_detailsList (0) also becomes set to nov 8th and all the subsequent rows till 6th row is overwritten with the new values correspondingly. I dont know why this is happening.I would really appreciate if Anybody can help me please.

List<Model.Shiftdetails> schdetails = new List<Model.Shiftdetails>();
bindingSource1.DataSource = schdetails;
gridControl1.DataSource = bindingSource1;

int k=0;

for (int i = 0,j=0; i <=cycledays; i+=7)
{
    foreach (Model.Shiftdetails detail in sch.shift_detailsList)
    {
        Model.Shiftdetails cycleschdetails = new Model.Shiftdetails();
        cycleschdetails = detail;
        cycleschdetails.shift_date = dtCycleStartDate.DateTime.Date.AddDays(j);

        j++;
        k++;

        if (cycleschdetails.schedule == null)
        {
            cycleschdetails.schedule = new Model.Schedule { id = -1, schedule_info = new Model.ScheduleInfo { schedule_name = crm.GetString("NoShift") }, schedule_flexible = true };
        }

        bindingSource1.Add(cycleschdetails);
        bindingSource1.MoveNext();

       if (k > cycledays)
           break;

    }

    if (k > cycledays)
        break;
} 


values of binding source are now:
datasource[0] date=nov 8
datasource[1] date=nov 9
datasource[2] date=nov 10
datasource[3] date=nov 11
datasource[4] date=nov 12
datasource[5] date=nov 13
datasource[6] date=nov 14
datasource[7] date=nov 8
datasource[8] date=nov 9
datasource[9] date=nov 10
datasource[10] date=nov 11
datasource[11] date=nov 12
datasource[12] date=nov 13`enter code here`
datasource[13] date=nov 14

Thanks

Upvotes: 1

Views: 119

Answers (1)

bamblack
bamblack

Reputation: 3779

The issue with the code there is that when you do this:

cycleschdetails = detail;

cycleschdetails is a reference to detail. So any changes you make on cycleschdetails will also be made on detail. This works just fine for the first time around, but then second time around, when you loop over those same objects again detail will be modified again, causing both of the objects that have references to it to be changed.

The way to get around this is: rather than setting the object as a reference to detail, set the properties on the objects equal to one another. As long as they are primitive types (strings, ints, decimals, etc...) they won't have references created between them.

Something like:

cycleschdetails.SomeString = detail.SomeString;
cycleschdetails.SomeInt = detail.SomeInt;

However, if you have nested objects within there, you will run in to the same problem and will have to do the same thing on those.

This is bad

cycleschdetails.CustomObject = detail.CustomObject;

This is good

cycleschdetails.CustomObject.SomeProperty = detail.CustomObject.SomeProperty;

You get the idea ;) The basic problem is, objects have references tied to them when they are set equal to something else, primitive types, however, don't.

To provide a full example (just because I like the sound of my own voice ;) )

class Program {
    static void Main(string[] args) {
        TestClass test1 = new TestClass() {
            SomeInt = 1
        };
        Console.WriteLine(test1.SomeInt); // outputs 1

        TestClass test2 = test1;
        test2.SomeInt = 2;
        Console.WriteLine(test1.SomeInt); // ouputs 2

        TestClass test3 = new TestClass();
        test3.SomeInt = test1.SomeInt;
        test3.SomeInt = 4;
        Console.WriteLine(test1.SomeInt); // ouputs 2 still

        Console.ReadLine();            
    }
}

public class TestClass {
    public int SomeInt { get; set; }
}

Upvotes: 2

Related Questions