如何设置属性网格的列宽?

问题描述 投票:0回答:9

我在应用程序中使用属性网格来显示对象属性的名称和值。

默认情况下,列的宽度(名称和属性)的比例为 50:50。 我们可以选择滑动分离器来改变这个宽度。 我想知道如何以编程方式调整这个宽度,以便可以将其设置为 25:75。

c# .net winforms propertygrid
9个回答
16
投票

我发现hamed的解决方案运行不可靠。我通过以编程方式模拟用户拖动列分割器来解决这个问题。以下代码使用反射来执行此操作:

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 });
}

9
投票

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(值);

您不需要在其他地方调用它。拨打一次即可享受。


4
投票

this中提到的答案:

没有属性可以做到这一点,你必须破解控件。首先添加此代码:

    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);

2
投票

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 });
}

0
投票

我已经成功使用了开源扩展PropertyGrid,您可以在http://www.codeproject.com/Articles/13630/Add-Custom-Properties-to-a-PropertyGrid找到。它有两种您感兴趣的方法:

AutoSizeProperties - 自动移动分割器以更好地适应所有 显示的属性。 MoveSplitterTo - 按指示移动拆分器 由用户在参数中设置。

您可以计算 PropertyGrid 的

Width
的 25% 并用它设置
MoveSplitterTo

我实际上使用

AutoSizeProperties
,因为它会自动移动分离器以紧贴标签。注意,设置完
AutoSizeProperties
之后还需要设置
SelectedObject


0
投票

由于获取字段

gridView
对我不起作用,我采取了另一种方法,您可以从
Controls
属性获取 GridView。

然而,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;
                    }
                }
            }
        }
    }

0
投票

我想记住并恢复我的 WinForms 应用程序的 PropertyGrid 拆分器位置的最后设置。

如何实现这一点可以从 Microsoft PropertyGrid 和 PropertyGridView 源代码中得出(请参阅下面的链接)。

在 Form_Load 中的 WinForms 应用程序中,我设置了保存在应用程序设置中的已保存分割器位置值(由 PropertyGridView 中的 _labelRatio 表示)。 在 Form_Closing 中,我获取当前拆分器位置值(由 PropertyGridView 中的 _labelRatio 表示)并将它们存储在我的应用程序的“设置”中。

这里如何获取和设置 PropertyGrid 的 LabelRatio 值:

public static double GetLabelRatio(this PropertyGrid grid)
{
    var (gridView, labelRatioField) = grid.GetGridViewAndLabelRatioField();
    return (double)(labelRatioField?.GetValue(gridView) ?? 2);
}

public static void SetLabelRatio(this PropertyGrid grid, double value)
{
    var (gridView, labelRatioField) = grid.GetGridViewAndLabelRatioField();
    labelRatioField?.SetValue(gridView, value);
}

private static (Control? gridView, FieldInfo? labelRatioField) GetGridViewAndLabelRatioField(this PropertyGrid grid)
{
    var gridViewField = grid?.GetType().GetField("_gridView", BindingFlags.Instance | BindingFlags.NonPublic);
    var gridView = gridViewField?.GetValue(grid) as Control;
    var labelRatioField = gridView?.GetType().GetField("_labelRatio", BindingFlags.Instance | BindingFlags.Public);
    return (gridView, labelRatioField);
}

链接:

https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.propertygrid?view=windowsdesktop-9.0

https://github.com/dotnet/winforms/blob/62ebdb4b0d5cc7e163b8dc9331dc196e576bf162/src/System.Windows.Forms/src/System/Windows/Forms/Controls/PropertyGrid/PropertyGrid.cs


-1
投票

一个特殊的用例,可能对某人有用: 我将 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 });
    }

-4
投票

您可以使用 Smart PropertyGrid.Net 代替 propertygrid 并使用以下代码更改比率:

propertyGrid1.LabelColumnWidthRatio = 0.25;
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.