Как установить ширину столбца таблицы свойств?

Я использую сетку свойств в своем приложении для отображения имени и значения свойств объекта.

По умолчанию ширина столбцов (имя и свойство) составляет 50:50. и у нас есть возможность сдвинуть сплиттер, чтобы изменить эту ширину. Я хотел бы знать, как эта ширина может быть отрегулирована программно так, чтобы она могла быть установлена, скажем, 25:75.

8 ответов

Решение

Как в этом ответе упоминается:

Там нет собственности, чтобы сделать это, и вы должны взломать контроль. Сначала добавьте этот код:

    public static void SetLabelColumnWidth(PropertyGrid grid, int width)
{
    if (grid == null)
        throw new ArgumentNullException("grid");

    // get the grid view
    Control view = (Control)grid.GetType().GetField("gridView", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(grid);

    // set label width
    FieldInfo fi = view.GetType().GetField("labelWidth", BindingFlags.Instance | BindingFlags.NonPublic);
    fi.SetValue(view, width);

    // refresh
    view.Invalidate();
}

и назовите это с размером, который вы хотите. как это:

SetLabelColumnWidth(propertyGrid1, 100);

Я обнаружил, что решение Хамед не работает надежно. Я решил это, программно моделируя пользователя, перетаскивающего разделитель столбцов. Следующий код использует отражение, чтобы сделать это:

public static void SetLabelColumnWidth(PropertyGrid grid, int width)
{
    if(grid == null)
        return;

    FieldInfo fi = grid.GetType().GetField("gridView", BindingFlags.Instance | BindingFlags.NonPublic);
    if(fi == null)
        return;

    Control view = fi.GetValue(grid) as Control;
    if(view == null)
        return;

    MethodInfo mi = view.GetType().GetMethod("MoveSplitterTo", BindingFlags.Instance | BindingFlags.NonPublic);
    if(mi == null)
        return;
    mi.Invoke(view, new object[] { width });
}

Ответ 2019

Другие ответы на этой странице содержат специальные улучшения по сравнению с версиями C# и комментариями пользователей.

Я выбрал лучшее рабочее решение и создал метод расширения.

public static class PropGridExtensions
{
    public static void SetLabelColumnWidth(this PropertyGrid grid, int width)
    {
        FieldInfo fi = grid?.GetType().GetField("gridView", BindingFlags.Instance | BindingFlags.NonPublic);
        Control view = fi?.GetValue(grid) as Control;
        MethodInfo mi = view?.GetType().GetMethod("MoveSplitterTo", BindingFlags.Instance | BindingFlags.NonPublic);
        mi?.Invoke(view, new object[] { width });
    }
}

Применение:

В событии Form_Load() вызовите его прямо в сетке свойств следующим образом:

myPropertyGrid.SetLabelColumnWidth(значение);

Вам не нужно никуда называть это. Звоните один раз и наслаждайтесь.

Версия для Framework 4.0 (мне пришлось использовать BaseType). Метод используется в классе, унаследованном от PropertyGrid:

private void SetLabelColumnWidth(int width)
{
    FieldInfo fi = this.GetType().BaseType.GetField("gridView", BindingFlags.Instance | BindingFlags.NonPublic);
    object view = fi.GetValue(this);
    MethodInfo mi = view.GetType().GetMethod("MoveSplitterTo", BindingFlags.Instance | BindingFlags.NonPublic);

    mi.Invoke(view, new object[] { width });
}

Я добился успеха с расширенной PropertyGrid с открытым исходным кодом, которую вы можете найти по адресу http://www.codeproject.com/Articles/13630/Add-Custom-Properties-to-a-PropertyGrid. У вас есть два метода, которые вас заинтересуют:

AutoSizeProperties - автоматически перемещать разделитель, чтобы лучше соответствовать всем показанным свойствам. MoveSplitterTo - Переместить разделитель, как указано пользователем в параметре.

Вы можете рассчитать 25% от Width PropertyGrid и установить MoveSplitterTo с этим.

Я на самом деле использую AutoSizeProperties тем не менее, так как он автоматически перемещает сплиттер, чтобы плотно прилегать к этикеткам. Обратите внимание, что вам нужно установить AutoSizeProperties после того, как вы установили SelectedObject,

Особый вариант использования, который может быть кому-то полезен: я использую PropertyGrid с DesignSurface, и ширина столбца метки сужается при каждом изменении значения. Чтобы сохранить ширину столбца метки, установленную пользователем до того, как у меня сработало следующее:

public UcPropertyGridHost(...)
        {
            ...
            propGrid.PropertyValueChanged += OnPropertyValueChanged;
        }

private void OnPropertyValueChanged(object p_s, PropertyValueChangedEventArgs p_e)
        {
            var iWidth = GetLastLabelWidth();

            //do other things you want to

            SetLabelColumnWidth(propGrid, (int)iWidth);
        }

private int GetLastLabelWidth()
        {
            var iDefaultLabelColumnWidth = propGrid.Width / 2;

            var oFieldInfo = propGrid.GetType().GetField("gridView", BindingFlags.Instance | BindingFlags.NonPublic);
            if (oFieldInfo == null) return iDefaultLabelColumnWidth;

            if (!(oFieldInfo.GetValue(propGrid) is Control oView)) return iDefaultLabelColumnWidth;

            var oFileInfo = oView.GetType().GetField("labelWidth", BindingFlags.Instance | BindingFlags.NonPublic);
            if (oFileInfo == null) return iDefaultLabelColumnWidth;

            return (int)oFileInfo.GetValue(oView);
        }

и код взят отсюда:

private void SetLabelColumnWidth(PropertyGrid p_oGrid, int p_iWidth)
    {
        if (p_oGrid == null) return;

        var oFieldInfo = p_oGrid.GetType().GetField("gridView", BindingFlags.Instance | BindingFlags.NonPublic);
        if (oFieldInfo == null) return;

        if (!(oFieldInfo.GetValue(p_oGrid) is Control oView)) return;

        var oMethodInfo = oView.GetType().GetMethod("MoveSplitterTo", BindingFlags.Instance | BindingFlags.NonPublic);
        if (oMethodInfo == null) return;

        oMethodInfo.Invoke(oView, new object[] { p_iWidth });
    }

С момента получения поляgridViewу меня не сработало, я применил другой подход, где вы можете получить GridView изControlsсвойство.

GridView, однако, имеет типSystem.Windows.Forms.PropertyGridInternal.PropertyGridView, который, как вы уже догадались, является внутренним.

Но все, что нас волнует на данный момент, — это элемент управления, который на самом деле имеет методMoveSplitterTo, поэтому мы перечисляем элементы управления, пока не получим то, что хотим, а затем просто вызываем метод.

          public class PropertyGridEx : PropertyGrid
    {
        private int splitterPosition;
        public int SplitterPosition
        {
            get => splitterPosition;
            set
            {
                splitterPosition = value;

                foreach (var control in Controls)
                {
                    if (control.GetType().GetMethod("MoveSplitterTo", BindingFlags.Instance | BindingFlags.NonPublic) is MethodInfo method)
                    {
                        method.Invoke(control, new object[] { value });
                        break;
                    }
                }
            }
        }
    }

Вы можете использовать Smart PropertyGrid.Net вместо propertygrid и изменить соотношение с помощью этого кода:

propertyGrid1.LabelColumnWidthRatio = 0.25;
Другие вопросы по тегам