2009-06-26 59 views
4

This question(及其答案)解釋了爲什麼您無法輕鬆地將DataGridView綁定到接口類型並獲取從基接口繼承的屬性的列。綁定到接口並顯示基接口中的屬性

建議的解決方案是實現一個自定義TypeConverter。我的嘗試如下。但是,創建綁定到ICamel的DataSource和DataGridView仍然只會導致一列(Humps)。我不認爲我的轉換器正被.NET用來決定它可以看到的ICamel的屬性。我究竟做錯了什麼?

[TypeConverter(typeof(MyConverter))] 
public interface IAnimal 
{ 
    string Name { get; set; } 
    int Legs { get; set; } 
} 

[TypeConverter(typeof(MyConverter))] 
public interface ICamel : IAnimal 
{ 
    int Humps { get; set; } 
} 

public class MyConverter : TypeConverter 
{ 
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 
    { 
     if(value is Type && (Type)value == typeof(ICamel)) 
     { 
      List<PropertyDescriptor> propertyDescriptors = new List<PropertyDescriptor>(); 
      foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(typeof(ICamel))) 
      { 
       propertyDescriptors.Add(pd); 
      } 
      foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(typeof(IAnimal))) 
      { 
       propertyDescriptors.Add(pd); 
      } 
      return new PropertyDescriptorCollection(propertyDescriptors.ToArray()); 
     } 
     return base.GetProperties(context, value, attributes); 
    } 

    public override bool GetPropertiesSupported(ITypeDescriptorContext context) 
    { 
     return true; 
    } 
} 
+0

您可能會發現有兩個其他的帖子很有趣:http://stackoverflow.com/questions/749542#750481和http://stackoverflow.com/questions/882214#882246 – 2009-06-26 11:55:28

回答

2

DataGridView不使用TypeConverter;使用TypeConverter

如果它涉及像DataGridView這樣的列表控件,那麼其他答案是錯誤的。

要在名單上提供的自定義屬性,你需要之一:該類型

兩者都是不平凡的

  • ITypedList數據源
  • TypeDescriptionProvider上。

+0

謝謝。將TypeDescriptionProvider應用於接口是不可能的,但在我的數據源中實現`ITypedList`在運行時完美工作。在設計時看到我的自定義屬性會很好,但我認爲我可以找到一個解決方法,這將是足夠的。 – spatulon 2009-06-26 12:24:38

0

我的建議是建立一個接口說,「重新實現了」您想要的propertys:

比方說,你有兩個接口:

public interface IHasName1 
{ 
    String Name1 { get; set; } 
} 

public interface IHasName2 : IHasName1 
{ 
    String Name2 { get; set; } 
} 

和實現IHasName2類:

public class HasTwoNames : IHasName2 
{ 
    #region IHasName1 Member 
    public string Name1 { get; set; } 
    #endregion 

    #region IHasName2 Member 
    public string Name2 {get; set; } 
    #endregion 
} 

現在,thx爲了弄清楚順便說一句,如果你有一個帶有具體類型HasTwoNames的對象的列表,並且你將該列表綁定到一個dgv,它只會顯示成員(Name2)o f IHasName2。

A「解決辦法」是創建一個新的接口「IHasEverything」從IHasName2繼承,因此從IHasName1和重新實現了Propertys你在你的綁定需要(你可以做到這一點與新語句

public interface IHasEverything : IHasName2 
{ 
    new String Name1 { get; set; } 
    new String Name2 { get; set; } 
} 

現在你的具體類 「HasTwoNames」 需要實現IHasEverything,太:

public class HasTwoNames : IHasName2, IHasEverything 
{ 
    ... 
} 

可以將此列表綁定到一個DataGridView:

public List<IHasEverything> elements = new List<IHasEverything> { 
     new HasTwoNames { Name1 = "Name1", Name2 = "Name2"}, 
     new HasTwoNames { Name1 = "Name3", Name2 = "Name4"}, 
    }; 

我知道這只是一種解決方法,只有在您可以修改實現類時纔有可能。但它的工作。 (如果您從IHasName2一個屬性,代碼仍然會編譯,但你得到的IHasEverything不需要新的關鍵字的警告。

1

我的解決方法發生在DGV的結合。 我確實需要,基接口和繼承接口保持相同的結構,只是因爲我做了其他事情寬度最後的concerete類,不僅顯示DataGridView上的數據。因此,舉例來說:

interface IGenericPerson 
{ 
    int ID { get; set; } 
    string Name { get; set; } 
} 

interface IOperator : IGenericPerson 
{ 
    bool IsAdmin { get; set; } 
} 

具體類:

class Operator : IOperator 
{ 
    public Operator(){} 

    public Operator(int id, string name, bool isAdmin) 
    { 
     this.ID = id; 
     this.Name = name; 
     thsi.IsAdmin = isAdmin; 
    } 

    public int ID { get; set; } 
    public string name { get; set; } 
    public bool IsAdmin { get; set; } 
} 

,並在網關類:

public IList<IOperator> GetOperators() 
{ 
    IList<IOperator> list = new List<IOperator>(); 

    list.add(new Operator(112, "Mark Twain", false); 
    list.add(new Operator(112, "Charles Manson", false); 
    list.add(new Operator(112, "Richard Nixon", true); 

    return list; 
} 

現在,如果我嘗試一個DataGridView綁定這樣的:

Gateway gt = new Gateway(); 
dgv.DataSource = gt.GetOperators(); 

我得到一個DataGridView與來自IOperator接口的唯一bool IsAdmin列,不是ID,也不是來自其基本接口的Name屬性。

,但如果我這樣做:

Gateway gt = new Gateway(); 

IList<IOperator> list = gt.GetOperators(); 

IList<Operator> ds = new List<Operator>(); 

foreach(IOperator op in list) 
    ds.add((Operator)op); 

dgv.DataSource = ds; 

一切工作以正確的方式。

以這種方式我不需要改變intarfaces鏈的結構,對其他目的有用,只有qhen顯示數據我只是插入上面的代碼片段。