简体   繁体   English

c#winforms-更改数组的值不起作用

[英]c# winforms - changing value of array doesn't work

In form1 class I have: 在form1类中,我有:

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? 从数组设置表单属性有C#限制吗?

Color is a structure in C#, which is copied during assignments. Color是C#中的一种结构,在分配过程中会被复制。 That means when you assign: 这意味着您分配:

clr[0,0] = form1.btn1Color;

It assigns a copy of the value of form1.btn1Color to clr[0,0] . 它将form1.btn1Color值的副本分配给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. 实际上,即使Colorclass而不是struct ,结果也一样,因为在这种情况下,您将覆盖引用。

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 . 如果要分配数组以修改原始对象,则需要将对象包装在数组中,以引用具有持有Color成员的原始对象,因为Color是不可变的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: 更新 :根据您的后续问题,您可以做的一件事(确实有很多方法可以做到)是将Color包装在wrapper类中,并将该包装用于数组以及作为form1的成员:

    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: 然后,将form1.btn1Color更改为ColorHelper而不是Color ,这将起作用:

        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: 注意 :您还可以允许从转换Color - > ColorHolder为好,但是这可能会导致难以跟踪的错误,因为它能够:

        clr[0,0] = Color.Aqua;

Which would assign a new ColorHolder instead of changing the existing using Current . 这将分配一个新的 ColorHolder而不是使用Current来更改现有的ColorHolder Thus I'd avoid the Color -> ColorHolder conversion and stick with something like the above. 因此,我会避免Color - > ColorHolder转换并且用类似上面沾。

You could even generalize this Holder code to support any type, like: 您甚至可以泛化此Holder代码以支持任何类型,例如:

    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. 然后,您将拥有Holder<Color>或任何其他类型,而不是ColorHolder Again, this would be used like the following (assuming form1 's btn1Color member is now Holder<Color> ): 再次,它的用法如下(假设form1btn1Color成员现在为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;

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. 完成此操作后,按钮的Color属性与数组之间就没有关系。 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. 如果您确实想以这种方式通过数组设置按钮颜色,请存储按钮数组并在设置颜色时引用BackColor属性。

I think what you wanted to do instead was to 我想你想做的是

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

Properties and Variables are assigned from right to left. 属性和变量从右到左分配。 To assign a value to form.btn1Color , you need to assign a value like this: 要将值分配给form.btn1Color ,您需要分配一个值,如下所示:

form1.btn1Color = clr[0, 0];

Calling clr[0, 0] = form1.btn1Color; 调用clr[0, 0] = form1.btn1Color; only stores the color in the array, nothing else. 仅将颜色存储在数组中,仅此而已。 It does not remember the object itself. 它不记得对象本身。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM