我在我的 C# 项目中使用 .NET PropertyGrid 控件。
加载包含网格的表单时,水平分隔符(将设置与描述分开)位于默认位置。如何在 C# 中以编程方式更改该拆分器的位置?
此代码基于代码项目中的一篇文章 (http://www.codeproject.com/KB/grid/GridDescriptionHeight.aspx),其中引入了两个修复和一些清理。
private void ResizeDescriptionArea(PropertyGrid grid, int lines)
{
try
{
var info = grid.GetType().GetProperty("Controls");
var collection = (Control.ControlCollection)info.GetValue(grid, null);
foreach (var control in collection)
{
var type = control.GetType();
if ("DocComment" == type.Name)
{
const BindingFlags Flags = BindingFlags.Instance | BindingFlags.NonPublic;
var field = type.BaseType.GetField("userSized", Flags);
field.SetValue(control, true);
info = type.GetProperty("Lines");
info.SetValue(control, lines, null);
grid.HelpVisible = true;
break;
}
}
}
catch (Exception ex)
{
Trace.WriteLine(ex);
}
}
我在自己的项目中使用过它;它应该适合你。
您无法使用 PropertyGrid 控件公开的公共方法和属性来做到这一点,或者至少我找不到任何有用的东西。
您可能会尝试使用反射来获取显示设置或说明的属性网格的子控件,并尝试以编程方式设置它们的高度;我猜分离器只是对接,设置它的位置不会改变任何东西。
使用调试器查看 PropertyGrid 的非公共成员应该可以帮助您了解控件的内部结构。
这是 Matthew Ferreira 在 VB.Net 中的解决方案。谢谢马修,真是太好了!
Imports System.Reflection
Public Sub ResizeDescriptionArea(grid As PropertyGrid, lines As Integer)
Try
Dim info = grid.[GetType]().GetProperty("Controls")
Dim collection = DirectCast(info.GetValue(grid, Nothing), Control.ControlCollection)
For Each control As Object In collection
Dim type = control.[GetType]()
If "DocComment" = type.Name Then
Const Flags As BindingFlags = BindingFlags.Instance Or BindingFlags.NonPublic
Dim field = type.BaseType.GetField("userSized", Flags)
field.SetValue(control, True)
info = type.GetProperty("Lines")
info.SetValue(control, lines, Nothing)
grid.HelpVisible = True
Exit For
End If
Next
Catch ex As Exception
Trace.WriteLine(ex)
End Try
End Sub
我现在必须做出一些调整才能使这项工作正常进行。以下适用于 .NET 6:
public static class PropertyGridExtensions {
public static void ResizeDescriptionArea(this PropertyGrid grid, int lineCount) {
var helpControl = grid.Controls[0];
var helpControlType = helpControl.GetType();
const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
helpControlType.GetProperty("Lines")?.SetValue(helpControl, lineCount);
helpControlType.BaseType!.GetProperty("UserSized", bindingFlags)!.SetValue(helpControl, true);
grid.HelpVisible = true;
}
}
对于 Visual Basic .NET 用户(vb.net、Visual Studio 2022、2024 年 3 月):描述区域的内部控件名称从“DocComment”更改为“HelpPane”,其属性“UserSized”更名为“k__BackingField”。为了兼容所有以前的版本,我重写了该函数如下:
Public Sub ResizeDescriptionArea(grid As PropertyGrid, lines As Integer)
Try
Dim info = grid.[GetType]().GetProperty("Controls")
Dim collection = DirectCast(info.GetValue(grid, Nothing), Control.ControlCollection)
For Each control As Object In collection
Dim type = control.[GetType]()
If type.Name = "HelpPane" Or type.Name = "DocComment" Then
Const Flags As BindingFlags = BindingFlags.Instance Or BindingFlags.NonPublic
Dim fields = type.BaseType.GetFields(Flags)
' Method 1:
For Each fi As FieldInfo In fields
If fi.Name.Contains("UserSized") = True Then
Dim field = type.BaseType.GetField(fi.Name, Flags)
field.SetValue(control, True)
info = type.GetProperty("Lines")
info.SetValue(control, lines, Nothing)
grid.HelpVisible = True
Exit For
End If
Next
' or Method 2: (simpler)
' Dim field = type.BaseType.GetField("<UserSized>k__BackingField", Flags)
' field.SetValue(control, True)
' info = type.GetProperty("Lines")
' info.SetValue(control, lines, Nothing)
' grid.HelpVisible = True
' Exit For
End If
Next
Catch ex As Exception
Debug.WriteLine(ex)
End Try
End Sub