Search code examples
winformspropertygrid

Chop the text and display three dots in PropertyGrid of winforms


I would like to cut the extra text and display three dots(...) and when user clicks on the cell, everthing has to be displayed. how to calculate the width of the property grid cell and cut the text. Any help will be grateful.

Pictures are attached for explanation

Instead of this

I would like to achieve this

and it should vary according to the cell size


Solution

  • The property grid does not allow that and you cannot customize it to do so using any official way.

    However, here is some sample code that seems to work. It uses a TypeConverter to reduce the value from the grid's size.

    Use at your own risk as it relies on PropertyGrid's internal methods and may have an impact on performance, since it requires a refresh on the whole grid on each resize.

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
    
            // note this may have an impact on performance
            propertyGrid1.SizeChanged += (sender, e) => propertyGrid1.Refresh();
    
            var t = new Test();
            t.MyStringProperty = "The quick brown fox jumps over the lazy dog";
            propertyGrid1.SelectedObject = t;
        }
    
    }
    
    public class AutoSizeConverter : TypeConverter
    {
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (value == null)
                return null;
    
            // small trick to get PropertyGrid control (view) from context
            var view = (Control)context.GetService(typeof(IWindowsFormsEditorService));
    
            // bigger trick (hack) to get value column width & font
            int width = (int)view.GetType().GetMethod("GetValueWidth").Invoke(view, null);
            var font = (Font)view.GetType().GetMethod("GetBoldFont").Invoke(view, null); // or GetBaseFont
    
            // note: the loop is not super elegant and may probably be improved in terms of performance using some of the other TextRenderer overloads
            string s = value.ToString();
            string ellipsis = s;
            do
            {
                var size = TextRenderer.MeasureText(ellipsis, font);
                if (size.Width < width)
                    return ellipsis;
    
                s = s.Substring(0, s.Length - 1);
                ellipsis = s + "...";
            }
            while (true);
        }
    }
    
    public class Test
    {
        // we use a custom type converter
        [TypeConverter(typeof(AutoSizeConverter))]
        public string MyStringProperty { get; set; }
    }
    

    Here is the result (supports resize):

    enter image description here