Как создать свойство для хранения индекса выбранного значения из другого свойства? - PullRequest
3 голосов
/ 12 июня 2009

Мне нужна помощь по следующей проблеме:

У меня есть класс с двумя свойствами.

private byte m_selectedValue;
public byte SelectedValue
{
  get { return m_selectedValue; }
  set { m_selectedValue = value; }
}

private string[] m_possibleValues;
public string[] PossibleValues
{
  get { return m_possibleValues; }
  set { m_possibleValues = value; }
}

Возможные значения хранят список выбираемых значений. SelectedValue содержит индекс фактически выбранного значения.

В этом состоянии редактор свойств показывает индекс выбранного значения. Я хотел бы выбрать значение с помощью поля со списком в сетке свойств, тот же стиль, который используется со свойством Enum. Список комбинированного списка будет заполнен из свойства возможного значения.

С помощью этой статьи (http://www.codeproject.com/KB/cpp/UniversalDropdownEditor.aspx) мне удалось создать пользовательский редактор, который отображает выпадающий список на сетке свойств со значениями из свойства возможного значения. Я также могу выбрать значение, но по-прежнему в сетке свойств указывается индекс значения вместо самого значения.

Это модифицированный источник редактора (оригинал от CodeProject):

public class EnumParamValuesEditor : UITypeEditor
{
    private IWindowsFormsEditorService edSvc;

    public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
    {
        if ((context != null) && (context.Instance != null))
            return UITypeEditorEditStyle.DropDown;
        return UITypeEditorEditStyle.None;
    }

    public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        if ((context == null) || (provider == null) || (context.Instance == null))
            return base.EditValue(provider, value);
        edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
        if (edSvc == null)
            return base.EditValue(provider, value);
        ListBox lst = new ListBox();
        PrepareListBox(lst, context);
        lst.SelectedIndex = (byte)value;
        edSvc.DropDownControl(lst);
        if (lst.SelectedItem == null)
            value = null;
        else
            value = (byte)lst.SelectedIndex;
        return value;
    }

    private void PrepareListBox(ListBox lst, ITypeDescriptorContext context)
    {
        lst.IntegralHeight = true;
        string[] coll = ((EnumTerminalParam)context.Instance).PossibleValues;
        if (lst.ItemHeight > 0)
        {
            if ((coll != null) && (lst.Height / lst.ItemHeight < coll.Length))
            {
                int adjHei = coll.Length * lst.ItemHeight;
                if (adjHei > 200)
                    adjHei = 200;
                lst.Height = adjHei;
            }
        }
        else
            lst.Height = 200;
        lst.Sorted = true;
        FillListBoxFromCollection(lst, coll);
        lst.SelectedIndexChanged += new EventHandler(lst_SelectedIndexChanged);
    }

    void lst_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (edSvc == null)
            return;
        edSvc.CloseDropDown();
    }

    public void FillListBoxFromCollection(ListBox lb, ICollection coll)
    {
        lb.BeginUpdate();
        lb.Items.Clear();
        foreach (object item in coll)
            lb.Items.Add(item);
        lb.EndUpdate();
        lb.Invalidate();
    }

}

Конечно, для корректной обработки некоторых ситуаций требуются дальнейшие модификации (например, возможное значение пусто).

Так можно ли отобразить возможное значение [SelectedValue] вместо SelectedValue в редакторе свойств?

Ответы [ 2 ]

1 голос
/ 12 июня 2009

Вам необходимо присоединить пользовательский TypeConverter к вашему свойству SelectedValue и сделать возможное значение для просмотра недоступным TypeConverter будет отвечать за отображение строк в PropertyGrid вместо целых. В общем, вам нужно переопределить CanConvertFrom, CanConvertTo, ConvertFrom и ConvertTo. Если вы хотите получить свои пользовательские строки, используйте аргумент контекста, переданный этим методам, и вызовите свойство возможного значения в вашем целевом экземпляре. Это должно сделать это. Кажется, здесь вам не нужен пользовательский UITypeEditor.

0 голосов
/ 12 июня 2009

Вместо двух отдельных свойств, почему бы не связать их вместе в типе словаря. Намного проще в этом случае. С вашим индексом в качестве ключа и строкой [] в качестве значений. Только не ограничивайте себя байтом для индекса.

...