首页 > 解决方案 > PropertyGrid 滚动位置在设置时不会改变

问题描述

我有PropertyGrid一个 Windows 窗体应用程序。每当它SelectedObject发生变化时,它都会将其值重置VerticalScroll为 0。我需要它保持在原来的位置。下面的代码似乎没有做任何事情。我已经尝试PerformLayout了很多其他解决方案,但都没有成功。有任何想法吗?

int pos = MyGrid.VerticalScroll.Value;
MyGrid.SelectedObject = SomeDifferentObject;
MyGrid.VerticalScroll.Value = pos;

标签: c#.netwindowswinformspropertygrid

解决方案


VerticalScroll属性与 PropertyGrid 类无关。它引用VScrollBar控件的内部属性。Scroll 事件永远不会发生。
是控件的VScrollBarSystem.Windows.Forms.PropertyGridInternal.PropertyGridView控件,是一个不能直接访问的类。

无论如何,您都可以得到它,将 PropertyGrid 转换为 Control 或忽略Browsable(false)PropertyGrid 属性的Controls属性,然后找到子项,存储当前值,然后在更改属性VScrollBar后再次设置它。 请注意,这个新控件可以具有与以前不同数量的属性,滚动条将仅设置在之前的位置。 更准确地说,您可以获取设置 new 之前和之后显示的属性数量并执行相对滚动。SelectedObject

SelectedObject

在这里,我PropertyGridView通过AccessibilityObject.Rolewhich isAccessibleRole.Table找到它,但您也可以通过它的 Text ( "PropertyGridView") 找到它:

var vScroll = propertyGrid1.Controls.OfType<Control>()
    .Where(ctl => ctl.AccessibilityObject.Role == AccessibleRole.Table)
    .First().Controls.OfType<VScrollBar>().First();

var vScrollValue = vScroll.Value;
propertyGrid1.SelectedObject = [Some Other Object];
vScroll.Value = vScrollValue;

如果需要(如前所述),将滚动条重新定位在相同的相对位置,代码可能变为:

BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;

var propGrid = propertyGrid1.Controls.OfType<Control>()
    .Where(ctl => ctl.AccessibilityObject.Role == AccessibleRole.Table).First();
var totalProperties = (int)propGrid.GetType().GetField("totalProps", flags).GetValue(propGrid);

var vScroll = propGrid.Controls.OfType<VScrollBar>().FirstOrDefault();
if (vScroll != null && totalProperties > 0) {
    var vRelativeScroll = vScroll.Value / (float)totalProperties;
    propertyGrid1.SelectedObject = this.trackBar2;

    totalProperties = (int)propGrid.GetType().GetField("totalProps", flags).GetValue(propGrid);
    vScroll.Value = (int)(vRelativeScroll * totalProperties);
}

推荐阅读