2009-06-12 37 views
3

我需要以下问题的帮助:如何创建一个属性来存储另一个属性中所选值的索引?

我有一个有两个属性的类。

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

PossibleValues存储可选值的列表。 SelectedValue包含实际选定值的索引。

在此状态下,属性编辑器显示所选值的索引。我想在属性网格中使用组合框选择值,这与Enum属性使用的样式相同。组合框的列表将从PossibleValues属性填充。

在这篇文章的帮助下(http://www.codeproject.com/KB/cpp/UniversalDropdownEditor.aspx)我设法创建了一个自定义编辑器,用属性PossibleValues显示属性网格上的组合框。我也可以选择该值,但属性网格仍显示值的索引而不是值本身。

这是编辑器的修改的源(原来是从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(); 
    } 

} 

当然,这需要进一步的修改,以正确地处理某些情况下(例如在PossibleValues是空的)。

那么有可能在属性编辑器中显示PossibleValues [SelectedValue]而不是SelectedValue?

回答

1

您需要将自定义的TypeConverter附加到您的SelectedValue属性,并使PossibleValues不可浏览。 TypeConverter将负责在PropertyGrid中显示字符串而不是ints。所以基本上,你需要重写CanConvertFrom,CanConvertTo,ConvertFrom和ConvertTo。当你想获得你的自定义字符串时,使用传递给这些方法的context参数并在你的目标实例中调用你的PossibleValues属性。这应该可以做到。看起来你不需要任何自定义的UITypeEditor。

+0

我认为GetStandardValuesSupported和GetStandardValues用于在属性编辑器中显示组合框。不幸的是,GetStandardValues必须返回一个与属性本身属于同一类型元素的集合,至少根据http://msdn.microsoft.com/en-us/library/ayybcxe5.aspx。我如何使属性编辑器显示与ConvertFrom或ConvertTo方法的组合框? – starobrno 2009-06-15 14:40:23

0

而不是两个单独的属性,为什么不把它们绑定在一个Dictionary类型中。在这种情况下更容易使用。以索引作为关键字并将字符串[]作为值。只是不要将自己限制为索引的一个字节。

+0

如果我将字符串[]中的PossibleValues更改为字典,我仍然需要一个属性来存储当前选定的值。应用程序处理来自外部设备的信息,并在处理完信息后发回。我使用字节数据类型,因为此设备只接受从0到255的值。 – starobrno 2009-06-12 10:11:53

相关问题