如何创建一个属性来存储另一个属性所选值的索引?

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 包含实际选定值的索引。
在此状态下,属性编辑器显示所选值的索引。我想使用属性网格中的组合框选择值,与枚举属性使用的相同样式。组合框的列表将从 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?
2个回答

1
你需要将一个自定义的TypeConverter附加到你的SelectedValue属性上,并将PossibleValues设置为不可浏览。TypeConverter将负责在PropertyGrid中显示字符串而不是整数。因此,基本上,你需要覆盖CanConvertFrom、CanConvertTo、ConvertFrom和ConvertTo方法。当你想要获取自定义字符串时,在这些方法中使用传递给它们的context参数,并在目标实例中调用你的PossibleValues属性。这样就可以了。看起来在这里你不需要任何自定义的UITypeEditor。

我认为GetStandardValuesSupported和GetStandardValues用于在属性编辑器中显示组合框。不幸的是,根据http://msdn.microsoft.com/en-us/library/ayybcxe5.aspx,GetStandardValues必须返回与属性本身相同类型的元素集合。我该如何使用ConvertFrom或ConvertTo方法使属性编辑器显示组合框? - starobrno
是的,GetStandardValues将返回您的本机类型(byte)。这就是触发组合框的原因。ConvertFrom和ConvertTo将简单地执行转换以从您的自定义字符串转换/转换为字符串,以便在列表中显示字符串而不是字节。 - Nicolas Cadilhac

0

为什么不在字典类型中将两个单独的属性绑定在一起呢?在这种情况下,使用起来会更加容易。将索引作为键,字符串数组作为值。只是不要将索引限制为一个字节。


如果我将PossibleValues从string[]更改为Dictionary<int,string>,我仍然需要一个属性来存储当前选择的值。该应用程序处理来自外部设备的信息,并在处理信息后将其发送回去。我使用byte数据类型,因为此设备仅接受0到255之间的值。 - starobrno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接