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

发布于 2024-07-25 00:20:36 字数 3332 浏览 2 评论 0原文

我需要帮助解决以下问题:

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

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

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

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

借助本文 (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();
    }

}

当然,它需要进一步修改才能正确处理某些情况(例如,PossibleValues为空)。

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

I need help with the following problem:

I have a class with two properties.

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

The PossibleValues stores the list of the selectable values. The SelectedValue contains the index of the actually selected value.

In this state the property editor shows the index of the selected value. I would like to select the value using a combobox in the property grid, the same style used with an Enum property. The combobox's list would be populated from the PossibleValues property.

With the help of this article (http://www.codeproject.com/KB/cpp/UniversalDropdownEditor.aspx) I have managed to create a custom editor that show the combobox on the property grid with the values from the PossibleValues property. I can also select the value, but still the property grid shows the index of the value instead of the value itself.

This is the modified source of the editor (original is from 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();
    }

}

Of course, it needs further modifications to correctly handle some situations (ex. the PossibleValues is empty).

So is it possible to show the PossibleValues[SelectedValue] instead of the SelectedValue in the property editor?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

任性一次 2024-08-01 00:20:36

您需要将自定义 TypeConverter 附加到 SelectedValue 属性,并使 MaybeValues 不可浏览。 TypeConverter 将负责在 PropertyGrid 中显示字符串而不是整数。 所以基本上,您需要重写 CanConvertFrom、CanConvertTo、ConvertFrom 和 ConvertTo。 当您想要获取自定义字符串时,请使用传递给这些方法的上下文参数并在目标实例中调用您的 MaybeValues 属性。 那应该可以了。 似乎您在这里不需要任何自定义 UITypeEditor 。

You need to attach a custom TypeConverter to your SelectedValue property and make the PossibleValues non browsable. The TypeConverter will be responsible for showing strings in the PropertyGrid instead of ints. So basically, you need to override CanConvertFrom, CanConvertTo, ConvertFrom and ConvertTo. When you want to get your custom strings, use the context argument passed to these methods and call your PossibleValues property in your target instance. That should make it. Seems you don't need any custom UITypeEditor here.

小兔几 2024-08-01 00:20:36

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

Instead of two separate properties why not tie them together within a Dictionary type. So much easier to use in this case. With your index as the key and the string[] as values. Just don't limit yourself to a byte for the index.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文