Как создать свойство для хранения индекса выбранного значения из другого свойства?
-
13-09-2019 - |
Вопрос
Мне нужна помощь со следующей проблемой:
У меня есть класс с двумя свойствами.
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; }
}
Возможные затраты хранят список выбираемых значений. Выбранная Value содержит индекс фактического выбранного значения.
В этом состоянии редактор свойств показывает индекс выбранного значения. Я хотел бы выбрать значение, используя ComboBox в сетке свойств, тот же стиль, который используется со свойством Enum. Список Combobox будет заполнен собственностью SouptionValues.
С помощью этой статьи (http://www.codeproject.com/kb/cpp/universaldropdowneditor.aspx) Мне удалось создать пользовательский редактор, который показывает ComboBox в сетке свойств со значениями из свойства SouptionValues. Я также могу выбрать значение, но все же в сетке свойств показан индекс значения вместо самого значения.
Это модифицированный источник редактора (оригинал от 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] вместо выбранного Value в редакторе недвижимости?
Решение
Вам необходимо прикрепить пользовательский TypeConverter к свойству выбранного Value и сделать возможные невозможны. TypeConverter будет нести ответственность за показ строк в PropertyGrid вместо INT. Таким образом, в основном вам необходимо переопределить Canconvertfrom, Canconvertto, ConvertFrom и Convertto. Если вы хотите получить свои пользовательские строки, используйте контекстный аргумент, переданный в эти методы, и вызовите свое свойство возможных в вашем целевом случае. Это должно это сделать. Кажется, вам здесь не нужен пользовательский uitypeeditor.
Другие советы
Вместо двух отдельных свойств, почему бы не связать их вместе с словарным типом. Намного проще в использовании в этом случае. С вашим индексом в качестве ключа и строки [] как значения. Только не ограничивайте себя байтом для индекса.