2011-11-01 118 views
9

C#匿名類型的訪問,我在那裏用匿名類型的集合填充組合框:其他方法

var results = (from row in data.Tables[0].AsEnumerable() 
       select new { 
        Id = row.Field<int>("id"), 
        Name = row.Field<string>("Name 
       }).Distinct(); 

myComboBox.ValueMember = "Id"; 
myComboBox.DisplayMember = "Name"; 

foreach (var n in results) 
{ 
    myComboBox.Items.Add(n); 
} 

然後,在下拉列表中的SelectedIndexChanged方法,我想檢索所選的Id項,但我無法訪問「Id」屬性,在myComboBox.SelectedItem中是選定的對象。

private void myComboBox_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    if (myComboBox.SelectedItem != null) 
    { 
     var x = myComboBox.SelectedItem; 

      ¿¿¿ ??? 
    } 
} 

任何想法?

+0

如果你只是需要的ID你可以使用myCombobox.SelectedValue? – saus

+2

* dynamic *關鍵字會讓你陷入困境。匿名類型的成員具有*內部*可訪問性。換句話說,當您的UI代碼位於單獨的程序集中時,您無法訪問它們。這是非常普遍的,將UI與數據模型分離是一種值得追求的方式。這裏不要使用匿名類型。 –

+0

使用匿名和/或動態類型不是這裏的答案。你自己的輕量級類型有什麼問題? (或者,對於此特定示例,['KeyValuePair '](http://msdn.microsoft.com/en-us/library/5tbh8a42.aspx)?) – LukeH

回答

4

你也可以使用反射。

private void myComboBox_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    if (myComboBox.SelectedItem != null) 
    { 
     var x = myComboBox.SelectedItem; 
     System.Type type = x.GetType(); 
     int id = (int)type.GetProperty("Id").GetValue(obj, null); 
    } 
} 
+1

類型轉換技巧比反射速度快得多,但我不能說哪個更有可能繼續在未來版本的C#/ CLR中工作。 –

9

由於您使用的ID作爲valuemember的標識將被存儲爲myComboBox.SelectedItem.Value

0

可以使用dynamic關鍵字來代替var

1

如果您使用的是C#4.0,那麼使用動態關鍵字,否則,請定義一個包含id和名稱的類,而不是使用匿名類型或使用反射。

1

您需要最簡單的解決方案嗎?使用三個字段創建一個名爲SimpleEntity的類:Id,Description和Tag。這個類應該有一個構造函數接受一個對象,並且使用反射,你可以得到Id和Name並設置兩個字段。你也可以用Object來設置Tag屬性。通過這種方式,你只需要使用這個新類來填充組合,然後找回原始對象。 我希望它有幫助。

+0

如果構造函數接受三個參數(int,string,object),則可以避免反射, –

0

我想你會更好在這裏使用類似Tuple<int, string>的東西,而不是匿名類型,但它是可能做你想做的。同一個程序集中兩個具有相同字段名稱和字段類型的匿名類型在內部「摺疊」爲一個類型。您可以使用它來傳遞匿名類型實例,並使用泛型類型推斷在以後的日期對它們進行類型轉換。

請注意,這依賴於C#編譯器中的內部機制,因此不能保證它將繼續工作;但是,它適用於每個當前版本的具有匿名類型的C#。

更新:這實際上是明確在C#規格叫出來,所以這應該是完全安全的事:

在同一節目內指定的屬性的序列,兩個匿名對象初始化以相同的順序將產生相同的匿名類型的實例

另請注意,這僅適用單個組件內相同的名字和類型(不要讓規範的參照「程序」混淆你) 。要消耗來自另一個程序集的匿名類型,需要反射(並且,IMO通常是一個非常糟糕的主意。)但是,對於數據綁定方案(如您的),它工作正常。

public object foo; 

public void Create() 
{ 
    this.foo = new { Id = 1, Name = "Melvin" }; 
} 

public void Consume() 
{ 
    var x = new { Id = 0, Name = String.Empty }; 
    var y = this.Cast(this.foo, x); 
} 

public T Cast<T> (object o, T template) 
{ 
    return (T)o; 
}