2011-11-01 7 views
9

tôi đã một ComboBox nơi được lấp đầy bằng một bộ sưu tập của Anonymous Type:C# Anonymous Loại truy cập từ phương pháp khá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); 
} 

Sau đó, trong phương pháp SelectedIndexChanged của combobox, tôi muốn lấy Id của chọn mục, nhưng tôi không thể truy cập vào thuộc tính "Id", trong myComboBox.SelectedItem là đối tượng được chọn.

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

      ¿¿¿ ??? 
    } 
} 

Bất kỳ ý tưởng nào?

+0

nếu bạn chỉ cần id, bạn có thể sử dụng myCombobox.SelectedValue không? – saus

+2

Từ khóa * động * sẽ giúp bạn gặp rắc rối. Các thành viên của một loại ẩn danh có khả năng truy cập * nội bộ *. Hay nói cách khác, bạn không thể truy cập chúng khi mã giao diện người dùng của bạn ở trong một hội đồng riêng biệt. Điều này rất phổ biến, việc tách giao diện người dùng khỏi mô hình dữ liệu là một sự theo đuổi xứng đáng. Đơn giản chỉ cần không sử dụng một loại vô danh ở đây. –

+0

Sử dụng loại anon và/hoặc động không phải là câu trả lời ở đây. Có gì sai với loại nhẹ của riêng bạn? (Hoặc, đối với ví dụ cụ thể này, ['KeyValuePair '] (http://msdn.microsoft.com/en-us/library/5tbh8a42.aspx)?) – LukeH

Trả lời

4

Bạn cũng có thể sử dụng phản chiếu.

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

Bí quyết khắc phục lỗi nhanh hơn nhiều so với sự phản chiếu, mặc dù tôi không thể nói cái nào trong số đó có nhiều khả năng tiếp tục hoạt động trong các phiên bản C#/CLR trong tương lai. –

9

Vì bạn sử dụng Id như valuemember Id sẽ được lưu trữ như myComboBox.SelectedItem.Value

0

Bạn có thể sử dụng dynamic từ khóa thay vì var.

1

nếu bạn đang làm việc với C# 4.0, sau đó sử dụng từ khóa động, nếu không, hãy xác định lớp chứa id và tên thay vì sử dụng loại ẩn danh hoặc sử dụng phản chiếu.

1

Bạn có cần giải pháp đơn giản nhất? Tạo một lớp có tên SimpleEntity với ba trường: Id, Description và Tag. Lớp này nên có một hàm tạo chấp nhận một đối tượng và, sử dụng sự phản chiếu, bạn lấy Id và Name và thiết lập hai trường. Và bạn alse đặt thuộc tính Tag với Object. Bằng cách này, bạn chỉ cần điền vào combo bằng cách sử dụng lớp mới này và sau đó bạn lấy lại đối tượng gốc. Tôi hy vọng điều đó sẽ hữu ích.

+0

Bạn có thể tránh phản xạ nếu hàm tạo chấp nhận ba tham số (int, string, object) –

0

Tôi nghĩ bạn nên sử dụng một cái gì đó như Tuple<int, string> ở đây, không phải là loại ẩn danh, nhưng đó là có thể để làm những gì bạn muốn. Hai loại vô danh trong cùng một assembly có cùng tên trường và kiểu trường theo thứ tự giống nhau được "xếp" nội bộ thành một kiểu duy nhất. Bạn có thể sử dụng điều này để truyền các thể hiện kiểu ẩn danh xung quanh và, bằng cách sử dụng suy luận kiểu chung chung, nhập chúng vào một ngày sau đó.

Lưu ý rằng điều này phụ thuộc vào một cơ chế nội bộ trong trình biên dịch C#, vì vậy không đảm bảo nó sẽ tiếp tục hoạt động; nó hoạt động, tuy nhiên, trong mọi phiên bản hiện tại của C# có các kiểu ẩn danh.

Cập nhật: Đây là thực sự gọi ra một cách rõ ràng trong thư mục C# spec, vì vậy đây sẽ hoàn toàn an toàn để làm:

Trong cùng một chương trình, hai initializers đối tượng vô danh mà chỉ định một chuỗi các thuộc tính của cùng tên và các loại theo thứ tự sẽ tạo ra thể hiện của các loại vô danh cùng

cũng lưu ý rằng đây chỉ hoạt động trong một hội duy nhất (đừng để tham khảo của spec để một "chương trình" nhầm lẫn bạn) . Để tiêu thụ các kiểu vô danh từ một assembly khác đòi hỏi sự phản chiếu (và, IMO, nói chung là một ý tưởng rất xấu.) Tuy nhiên, đối với các kịch bản ràng buộc dữ liệu như của bạn, nó hoạt động tốt.

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; 
}