Как установить ширину столбца таблицы свойств?
Я использую сетку свойств в своем приложении для отображения имени и значения свойств объекта.
По умолчанию ширина столбцов (имя и свойство) составляет 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;