1. 程式人生 > >UserControl 中包含封裝了集合物件的屬性被設計器自動初始化所引起的錯誤!也有關於List的問題

UserControl 中包含封裝了集合物件的屬性被設計器自動初始化所引起的錯誤!也有關於List的問題

在CSDN上看到了一篇關於UserControl引起的問題,去重現了一下,並進行了一些小結。

自定義 UserControl 中包含封裝了 List <介面> 型別欄位的屬性,編譯後造成引用了該 UserControl 的窗體設計器無法顯示!

public partial class UserControl1 : UserControl
{
private List<Student> face;

//[Bindable(false), Browsable(false)]
//[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
public List<Student> Face
{
get { return face; }
set { face = value; }
}

public UserControl1()
{
InitializeComponent();

face = new List<Student>();
}
}

//[Serializable]
public class Student
{

//此處為了簡化,不加任何的變數和屬性
void Update() {//此處為空 }
}

}

在這個UserControl上隨便放些東西,為了簡化問題,我在這上面放了幾個Label標籤,以可以在Form中看到這個UserControl。

然後把這個編譯生成的UserControl拖放到Form當中,編譯,彈出:

建立元件"UserControl1"失敗。錯誤訊息為:(此處只摘取有用資訊,僅取了第一行的提示資訊)

“System.Runtime.Serialization.SerializationException :程式集"WindowsApplication5,Version 1.0.0.0, Culture = neutral, PublicKeyToken = null "中的型別 “WindowsApplication5.Student”未標記為可序列化”

同時還會彈出另一個錯誤對話方塊,如下提示:

屬性“Face”的程式碼生成失敗。錯誤是:“程式集“WindowsApplication5,Version 1.0.0.0, Culture = neutral, PublicKeyToken = null ”中的型別“WindowsApplication5.Student”未標記為可序列化。”

關閉彈出的對話方塊後,發現form1上並沒有顯示UserContro,但到form1的InitializeComponent()程式碼中,又發現有UserControl的新增程式碼。

到form1的resx中去看,沒有任何的資源顯示。

處理辦法:

1.既然通過提示,我們看到了WindowsApplication5.Student未標記為可序列化,查了一下網上的資料,去把這個Student序列化,很簡單,在Public Class Student上面加入一句[Serializable]。即可。

然後再進行編譯,結果又出現錯誤提示:

錯誤 1 無效的 Resx 檔案。未能載入 .RESX 檔案中使用的型別System.Collections.Generic.List`1[[WindowsApplication5.Student, WindowsApplication5, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089。請確保已在專案中添加了必要的引用。 行 130,位置5。 C:/Documents and Settings/sn00590/My Documents/Visual Studio 2005/Projects/WindowsApplication5/WindowsApplication5 /Form1.resx 130 5 WindowsApplication5。

這個錯誤是在Form1.resx中出現的,在解決方案中去找到這個檔案,開啟一下,其中有userControl1.Face這個資源條目,而其的型別和值均為 (Nothing/null),而這就是導致窗體設計器無法顯示的原因,刪除這條資源和InitializeComponent() 中 userControl1.Face的賦值語句,窗體設計器可以正常打開了,但問題是一但修改了窗體的內容,再次編譯時,Face 屬性又會被重新賦值,這個資源引用也仍會被加入! 
實際上,經過測試發現,自定義 UserControl 中所有封裝了集合物件的屬性都會被設計器自動初始化,比如:string[],只不過其不會影響設計器的行為。不知 MS 為什麼要這樣設計,感覺是幫了倒忙,很是讓人費解。

經測試發現,在拖放自定義控制元件時到窗體時, 實際上該自定義控制元件會被例項化一次。。 同時都會去呼叫一下它下面的屬性,但並不執行它。

有時也會彈出這個問題,與無效的Resx檔案,是相同的問題。
型別“WindowsApplication130.Student[]”的物件無法轉換為型別“WindowsApplication130.Student[]”。 這句話可以讓很多人瘋掉,因為它是相同的型別轉相同的型別 ,怎麼無法進行轉換呢。然後到Form1的InitializeComponent()中刪除掉控制元件相關的,併到Form1.resx中刪除掉那一行型別 和值均為(Nothing/null)。並在屬性上加入以下兩句,然後再把那個控制元件拖上來,即可。

解決辦法是:在屬性上加入以下兩句。
[Bindable(false), Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

老實說,上面這幾個問題很折磨人的,在網上搜了搜,或許是用的關鍵字不對,沒搜到些什麼東西。而且專案又緊,只有一發狠,花了些時間來研究它,寫在這,希望能幫助遇到相同問題的朋友。

====================================================================================

拖拽自定義控制元件到Form中時,有時會報“。。。未標記為可序列化”。一般情況只要在class上加上標籤[Serializable]
就可以解決了。但是特殊情況下,比如上文中提到的在類中使用了泛型公共屬性。在拖拽使用者控制元件的時候,系統會自動new一個該控制元件的無參建構函式,併為其公共屬性賦初始值。泛型不能隱式進行反序列化,所以就在窗體進行this.Controls.add(該控制元件)時彈出錯誤提示。當我們點確定時,VS將無止境的繼續彈出錯誤提示。按Esc鍵後,VS將停止彈出錯誤提示並自動刪除這條add語句。

在winform中,使用上文中的解決辦法,在屬性上面加標籤:
[Bindable(false), Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

在wince或winMobile中,使用DesignTimeAttributes.xmta檔案。在類中為泛型屬性新增上面的節點。如下所示:

 <Class Name="HWSoftware.IPSPSD.MobileControls.ListPanelBase">
  <DesktopCompatible>true</DesktopCompatible>
  <DesignTimeVisible>true</DesignTimeVisible>
  <Property Name="Items">
   <Bindable>false</Bindable>
   <Browsable>false</Browsable>
   <DesignerSerializationVisibility>
    <![CDATA[Hidden]]>
   </DesignerSerializationVisibility>
  </Property>
 </Class>

轉載自:http://hi.baidu.com/maj0123/item/8e1632f591a0d2c6a935a26e