1

In form1 class I have:

public Color Btn1Color
{
  get { return btn1.BackColor; }
  set { btn1.BackColor = value; }
}

In the Model class I have:

private Color[,] clr = new Color[50, 50];
clr[0, 0] = form1.btn1Color;
clr[0, 0] = Color.Aqua; //the color of my button does not visually change.
//But if i instead use this line it does visually change:
//form1.btn1Color = Color.Aqua;

Why doesn't the first way (just setting the array element) work? Is there a C# limitation of setting form properties from an array?

1
  • Is there a C# limitation of setting form properties from an array? - TBH, this wouldn't be my first guess... Commented Oct 19, 2011 at 13:52

4 Answers 4

4

Color is a structure in C#, which is copied during assignments. That means when you assign:

clr[0,0] = form1.btn1Color;

It assigns a copy of the value of form1.btn1Color to clr[0,0]. Thus, when you then say:

clr[0,0] = Color.Aqua;

You are overwriting the copy, not the original.

In fact, even if Color were a class instead of struct the result would be the same, because in that case you'd overwrite the reference.

If you wanted assigning the array to modify the original object, you would need to wrap the object in the array to refer back to the original object that has the member holding the Color, since Color is an immutable struct.

Update: based on your follow up question, one thing you could do (there are really many ways to do this) is to wrap the Color in a wrapper class, and use that wrapper for the array and as the member in form1 as well:

    public class ColorHolder
    {
        // construct ColorHolder from Color
        public ColorHolder(Color color)
        {
            Current = color;
        }

        // can assign ColorHolder to Color with implicit conversion
        public static implicit operator Color(ColorHolder value)
        {
            return value.Current;
        }

        // get or set current color
        public Color Current { get; set; }
    }

Then, change form1.btn1Color to be ColorHelper instead of Color and this works:

        ColorHolder[,] clr = new ColorHolder[50, 50];

        // sets current color of btn1Color to black.
        form1.btn1Color = new ColorHolder(Color.Black);

        // assign array location to the color holder
        clr[0, 0] = form1.btn1Color;

        // this changes the current color of form1's btn1Color
        clr[0, 0].Current = Color.Aqua;

Note: You could also allow a conversion from Color -> ColorHolder as well, but this could lead to hard-to-track bugs as it would allow:

        clr[0,0] = Color.Aqua;

Which would assign a new ColorHolder instead of changing the existing using Current. Thus I'd avoid the Color -> ColorHolder conversion and stick with something like the above.

You could even generalize this Holder code to support any type, like:

    public class Holder<T>
    {
        public Holder(T value)
        {
            Value = value;
        }

        public static implicit operator T(Holder<T> holder)
        {
            return holder.Value;
        }

        public T Value { get; set; }
    }

Then instead of ColorHolder you'd have Holder<Color> or any other type. Again, this would be used like the following (assuming form1's btn1Color member is now Holder<Color>):

        Holder<Color>[,] clr = new Holder<Color>[50, 50];

        form1.btn1Color = new Holder<Color>(Color.Black);

        clr[0, 0] = form1.btn1Color;

        // sets the Color in form1.btn1Color to Aqua...
        clr[0, 0].Value = Color.Aqua;
Sign up to request clarification or add additional context in comments.

2 Comments

How can I get it to overwrite the original? My idea was to store the button names in an array so that my array dimensions would match to the relevant button in a 50x50 block of buttons.
There's several ways it could be done, but you'd have to rethink your array. You could have the array be an array of the button itself, the problem is you want it to store the Color, which is a struct which is immutable and copy-by-value. So storing the Color itself won't do what you want.
1

I think what you wanted to do instead was to

clr[0, 0] = Color.Aqua;
form1.btn1Color = clr[0, 0] ;

2 Comments

How can I get it to overwrite the original? My idea was to store the button names in an array so that my array dimensions would match to the relevant button in a 50x50 block of buttons. ie btn17_48.
Do you mean you want to store key value pairs with keys as button name and value as color? You may use hashtable instead of an array.
1

Properties and Variables are assigned from right to left. To assign a value to form.btn1Color, you need to assign a value like this:

form1.btn1Color = clr[0, 0];

Calling clr[0, 0] = form1.btn1Color; only stores the color in the array, nothing else. It does not remember the object itself.

2 Comments

How can I get it to overwrite the original? My idea was to store the button names in an array so that my array dimensions would match to the relevant button in a 50x50 block of buttons. ie btn17_48.
You could use clr as a struct to store each button and their respective colors.
1

clr[0,0] = form1.btn1Color; assigns the current value of the button's colour to the array.

Once this is done there is no relationship between the button's Color property and the array. It's the value of the colour that's put into the array, not the reference to the button's background colour.

If you really want to set button colours through an array in this way, store an array of buttons and reference the BackColor property when you set the colour.

1 Comment

How can I get it to overwrite the original? My idea was to store the button names in an array so that my array dimensions would match to the relevant button in a 50x50 block of buttons.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.