2015-06-16 10 views
0

Я пытаюсь отобразить свойства моего класса Wall в сетке свойств. Сейчас мой класс стена выглядит следующим образом:Правильно отобразить список пользовательских объектов в Property Properties для Windows Forms

[TypeConverter(typeof(ExpandableObjectConverter))] 
public class WallType 
{ 
    #region _private variables and Properties 
    public string Name { get; set; } //Name of the wall to identify it. For the wall program, it is automatically generated (ex. E4-1 where E = exterior wall, 4 = 2x4, and 1 means first exterior wall defined) 
    public string Type { get; set; } //Type of wall (exterior, interior, etc.) 
    public bool IsMirrorable { get; set; } //Identifies if the wall is mirrorable or not 
    public Distance Height { get; set; } //Height of the wall from bottom to talk 
    public string StudPattern { get; set; } //Pattern in which the studs of the wall are laid out 
    public Distance StudSpacing { get; set; } //Spacing between each stud 
    public VaporBarrier Barrier { get; set; } 
    public LetIn LetInOfWall { get; set; } 
    public Sheathing SheathingUsed { get; set; } 
    [TypeConverter(typeof(ExpandableObjectConverter))] 
    public List<Member> Members { get; set; } 
    public bool HasLetIn { get; set; } 
    public bool HasCapPlate { get; set; } 
    public bool HasVaporBarrier { get; set; } 
    public bool HasSheathing { get; set; } 
    #endregion 

    /*Constructors and Methods not shown*/ 
} 

Когда я показываю экземпляр WallType на сетке свойств она выходит так:

enter image description here

Все выглядит хорошо КРОМЕ собственности членов. Сейчас все, что он делает, отображает емкость и количество. Я хочу, чтобы он отображал свойство имен каждого члена в списке. Я думал, что установка ExpandableObjectConverter над списком решит проблему, но это не так. Так что я пытался ставить пользовательские TypeConverter на вершине класса-членов

[TypeConverter(typeof(MemberObjectConverter))] 
public class Member 
{ 
    #region _private variables and Properties 
    public string Name { get; set; } //Name of the member used to uniquely identify it 
    public string Size { get; set; } //Size of the member (ex. 2x4) 
    public string Grade { get; set; } //Grade of the wood used to make the member 
    public Distance Length { get; set; } //Length of the member 
    public string Species { get; set; } //Type of wood the member is made of 
    public string Treatment { get; set; } //Type of treatment applied to the member 
    public string Other { get; set; } //Variable for other notes about the member 
    #endregion 
    /*Constructors and Methods not shown*/ 
} 

И, наконец, мой пользовательского типа преобразователь

namespace Wall_Program 
{ 
    /// <summary> 
    /// Extending the ExpandableObjectConverter to display member objects properly 
    /// </summary> 
    public class MemberObjectConverter : ExpandableObjectConverter 
    { 
     public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
     { 
      if (destinationType == typeof(Member)) 
      { 
       return true; 
      } 
      return base.CanConvertTo(context, destinationType); 
     } 

     public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
     { 
      if (sourceType == typeof(string)) 
      { 
       return true; 
      } 
      return base.CanConvertFrom(context, sourceType); 
     } 

     public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, System.Type destinationType) 
     { 
      if (destinationType == typeof(System.String) && value is Member) 
      { 
       Member m = (Member)value; 
       return "Name: " + m.Name + 
        ", Size: " + m.Size + 
        ", Grade: " + m.Grade + 
        ", Length: " + m.Length.Architectural + 
        ", Species: " + m.Species + 
        ", Treatment: " + m.Treatment + 
        ", Other: " + m.Other; 
      } 
      return base.ConvertTo(context, culture, value, destinationType); 
     } 

     public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
     { 
      if (value is string) 
      { 
       try 
       { 
        string s = (string)value; 
        int colon = s.IndexOf(':'); 
        int comma = s.IndexOf(','); 

        if (colon != -1 && comma != -1) 
        { 
         string name = s.Substring(colon + 1, (comma - colon - 1)); 

         colon = s.IndexOf(':', comma + 1); 
         comma = s.IndexOf(',', comma + 1); 
         string size = s.Substring(colon + 1, (comma - colon - 1)); 

         colon = s.IndexOf(':', comma + 1); 
         comma = s.IndexOf(',', comma + 1); 
         string grade = s.Substring(colon + 1); 

         colon = s.IndexOf(':', comma + 1); 
         comma = s.IndexOf(',', comma + 1); 
         Distance length = new Distance(s.Substring(colon + 1, (comma - colon - 1))); 

         colon = s.IndexOf(':', comma + 1); 
         comma = s.IndexOf(',', comma + 1); 
         string species = s.Substring(colon + 1, (comma - colon - 1)); 

         colon = s.IndexOf(':', comma + 1); 
         comma = s.IndexOf(',', comma + 1); 
         string treatment = s.Substring(colon + 1, (comma - colon - 1)); 

         colon = s.IndexOf(':', comma + 1); 
         string other = s.Substring(colon + 1); 

         Member m = new Member(name, size, grade, length, species, treatment, other); 
         return m; 
        } 
       } 
       catch 
       { 
        throw new ArgumentException("Can not convert '" + (string)value + "' to type Member"); 
       } 
      } 
      return base.ConvertFrom(context, culture, value); 
     } 
    } 
} 

Преобразователь пользовательского типа, имеющий какой-то эффект, потому что, когда я нажимаю на кнопку, чтобы вручную показать коллекцию, все указано правильно. Но я хочу, чтобы имена были тем, что показано вместо емкости и количества.

enter image description here

+0

Это может быть уместным: HTTP: //stackoverflow.com/questions/6307006/how -can-i-use-a-winforms-propertygrid-to-edit-a-list-of-strings – NoChance

+0

Его коллекция. Преобразователь этого типа просто разрушает 2 части. То, что вы просите, - довольно странный способ отображения элементов коллекции. Будете ли вы редактировать их на месте? Если вы хотите, чтобы свойство collection 'Members' выполняло что-то, для этого вам нужен настраиваемый конвертер. Похоже, что есть некоторые проблемы с конвертером элемента-члена, но до сих пор он не запускается – Plutonix

ответ

1

Это довольно необычно, как прокомментировал Plutonix, но вот способ сделать это.

Просто используйте следующий TypeConverter в свойстве Members. Поскольку PropertyGrid основан на свойствах, вам необходимо создать поддельные свойства, которые представляют каждый член. Вот что представляет класс MemberDescriptor здесь.

public class MyTypeConverter : TypeConverter 
{ 
    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
    { 
     if (destinationType != typeof(string)) 
      return base.ConvertTo(context, culture, value, destinationType); 

     List<Member> members = value as List<Member>; 
     if (members == null) 
      return "-"; 

     return string.Join(", ", members.Select(m => m.Name)); 
    } 

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

    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 
    { 
     List<PropertyDescriptor> list = new List<PropertyDescriptor>(); 
     List<Member> members = value as List<Member>; 
     if (members != null) 
     { 
      foreach (Member member in members) 
      { 
       if (member.Name != null) 
       { 
        list.Add(new MemberDescriptor(member, list.Count)); 
       } 
      } 
     } 
     return new PropertyDescriptorCollection(list.ToArray()); 
    } 

    private class MemberDescriptor : SimplePropertyDescriptor 
    { 
     public MemberDescriptor(Member member, int index) 
      : base(member.GetType(), index.ToString(), typeof(string)) 
     { 
      Member = member; 
     } 

     public Member Member { get; private set; } 

     public override object GetValue(object component) 
     { 
      return Member.Name; 
     } 

     public override void SetValue(object component, object value) 
     { 
      Member.Name = (string)value; 
     } 
    } 
} 

В качестве бонуса, я также добавил преобразование в строку так это выглядит лучше:

+0

Точно, что мне нужно, спасибо! Я заметил, что вы использовали имя kilroy, Styx fan? –

+0

Tex avery cartoons :-): http://www.kilroywashere.org/01-Images/MattThKilroy/Page4/KilroyWasHereSardineTin.jpg –