2011-10-19 23 views
1

在Form I類有:C#的WinForms - 改變陣列的價值不工作

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

在模型I類有:

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; 

爲什麼沒有第一種方法(只設置數組元素)工作?從數組中設置表單屬性是否存在C#限制?

+0

'是否有一個C#限制從數組設置表單屬性?' - TBH,這不會是我的第一個猜測... –

回答

4

Color是C#中的一個結構,它在賦值過程中被複制。這意味着,當你分配:

clr[0,0] = form1.btn1Color; 

它指定的form1.btn1Colorclr[0,0]值的副本。因此,當你說:

clr[0,0] = Color.Aqua; 

你正在覆蓋副本,而不是原來的。

實際上,即使Colorclass而不是struct,結果也是一樣的,因爲在這種情況下,您會覆蓋參考。

,如果你想分配陣列修改原來的對象,你就需要包裝的對象數組指回到了持有Color成員原來的對象,因爲Color是一個不可變struct

更新:根據你的跟進問題,有一件事你可能 DO(實際上有很多方法可以做到這一點)被包裹Color在一個包裝類,並使用該包裝的陣列和在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; } 
    } 

然後,更改form1.btn1ColorColorHelper,而不是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; 

注意:你可以還允許從Color轉換 - >ColorHolder爲好,但是這可能會導致難以跟蹤的錯誤,因爲它能夠:

 clr[0,0] = Color.Aqua; 

這將分配ColorHolder而不是改變現有使用Current。因此,我會避免Color - >ColorHolder轉換,並堅持像上面的東西。

你甚至可以概括這個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; } 
    } 

然後,而不是ColorHolder你不得不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; 
+0

我怎樣才能覆蓋原文?我的想法是將按鈕名稱存儲在一個數組中,這樣我的數組尺寸就可以匹配50x50塊按鈕中的相關按鈕。 – toop

+0

有幾種方法可以完成,但你必須重新考慮你的數組。你可以讓數組成爲按鈕本身的數組,問題是你希望它存儲Color,它是一個「不變的,按值複製的」struct。所以存儲'Color'本身不會做你想做的。 –

1

clr[0,0] = form1.btn1Color;將按鈕顏色的當前值分配給數組。

完成此操作後,按鈕的顏色屬性與數組之間沒有關係。它是放入數組中的顏色的,而不是對按鈕背景顏色的引用。

如果您確實想以這種方式設置按鈕顏色,請存儲一組按鈕顏色並在設置顏色時引用BackColor屬性。

+0

我怎樣才能得到它覆蓋原來的?我的想法是將按鈕名稱存儲在一個數組中,這樣我的數組尺寸就可以匹配50x50塊按鈕中的相關按鈕。 – toop

1

我想你想做的事,而不是什麼是

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

我怎樣才能覆蓋原文?我的想法是將按鈕名稱存儲在一個數組中,這樣我的數組尺寸就可以匹配50x50塊按鈕中的相關按鈕。即btn17_48。 – toop

+0

你的意思是你想存儲鍵值對作爲按鈕名稱和值作爲顏色?你可以使用散列表而不是數組。 – Birey

1

屬性和變量分配從右到左。將值分配給form.btn1Color,你需要分配一個值,像這樣:

form1.btn1Color = clr[0, 0]; 

調用clr[0, 0] = form1.btn1Color;只存儲陣列中的顏色,沒有別的。它不記得對象本身。

+0

我怎樣才能覆蓋原文?我的想法是將按鈕名稱存儲在一個數組中,這樣我的數組尺寸就可以匹配50x50塊按鈕中的相關按鈕。即btn17_48。 – toop

+0

您可以使用'clr'作爲結構來存儲每個按鈕及其各自的顏色。 –