PropertyGrid显示文本框内联,而不是下拉列表

时间:2014-05-23 13:57:40

标签: c# user-interface propertygrid

This question (How to create a PropertyGrid editor that limits a string to n characters)几乎完全符合我的需要,但我不想使用下拉列表,而是希望编辑在网格本身中发生。

enter image description here

UITypeEditorEditStyle似乎没有多大帮助,因为将其设置为None会完全消除文本框控件。

或者,是否有更简单的方法来访问控件用于挂钩事件的TextBox?

最终,我正在寻找一个文本输入小部件,它限制输入的内容1.完成内联,以及2.无需等到用户停止输入以给出错误或截断输入。

1 个答案:

答案 0 :(得分:2)

您可以使用TypeConverter,一旦输入文本就会限制文本。这只会使文本框失去焦点。让我们假设我有这个类,我想用属性网格编辑:

public class MyClass
{
    [TypeConverter(typeof(MyTypeConverter))]
    public string MyText { get; set; }
}

以下是执行此操作的类型转换器代码:

public class MyTypeConverter : TypeConverter
{
    public const int MaxLength = 10;

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(string);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        return Truncate(value as string, MaxLength);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        return Truncate(value as string, MaxLength);
    }

    private static string Truncate(string value, int maxLength)
    {
        if (value == null)
            return null;

        return value.Length <= maxLength ? value : value.Substring(0, maxLength);
    }
}

否则,你可以破解网格,就像我在这里演示的那样。它不是UITypeEditor,因为底层文本框是为所有项共享的。以下方法基于选择事件。同样,这是我要编辑的另一个类:

public class MyClass
{
    [Editor(typeof(NoneEditor), typeof(UITypeEditor))]
    public string MyText { get; set; }

    public string MyOtherText { get; set; }
}

请注意,MyText属性使用&#34;标记&#34;编辑什么都不做:

public class NoneEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.None;
    }
}

我可以像这样挂钩网格:

propertyGrid1.SelectedGridItemChanged += OnPropertyGridSelectedGridItemChanged;

    public static void OnPropertyGridSelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
    {
        PropertyGrid pg = (PropertyGrid)sender;
        GridItem item = e.NewSelection;

        // yes, a grid item is also an IServiceProvider
        IServiceProvider sp = (IServiceProvider)item;

        // get the property grid view control
        IWindowsFormsEditorService svc = (IWindowsFormsEditorService)sp.GetService(typeof(IWindowsFormsEditorService));

        // WARNING: hack time! this uses private members, so use at your own risks...
        TextBox edit = (TextBox)svc.GetType().GetProperty("Edit", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(svc, null);

        // is this our funky stuff?
        if (item.PropertyDescriptor.GetEditor(typeof(UITypeEditor)) is NoneEditor)
        {
            edit.MaxLength = 10;
            edit.BackColor = Color.Blue;
        }
        else // don't forget to reset the edit box here
        {
            edit.MaxLength = int.MaxValue;
            edit.BackColor = Color.White;
        }
    }