PropertyGrid 滚动位置在设置时不改变
PropertyGrid scroll position not changing when set
我在 Windows Forms 应用程序中有一个 PropertyGrid
。每当它的 SelectedObject
发生变化时,它会将其 VerticalScroll
值重置为 0。我需要它保持原样。下面的代码似乎没有做任何事情。我已经尝试了 PerformLayout
和许多其他解决方案,但都没有成功。有什么想法吗?
int pos = MyGrid.VerticalScroll.Value;
MyGrid.SelectedObject = SomeDifferentObject;
MyGrid.VerticalScroll.Value = pos;
VerticalScroll
属性 与 PropertyGrid class 无关。它引用 VScrollBar
控件的内部属性。 Scroll 事件永远不会上升。
VScrollBar
是 System.Windows.Forms.PropertyGridInternal.PropertyGridView
控件的子控件,class 不能直接访问。
无论如何都可以得到它,将 PropertyGrid 转换为 Control 或忽略 PropertyGrid 的 Controls
属性 的 Browsable(false)
属性,然后找到 VScrollBar
子项,存储当前值然后在更改 SelectedObject
属性.
后再次设置它
请注意,这个新控件可以具有与以前不同数量的属性,滚动条将只设置在以前的位置。
为了更加 精确 ,您可以获得设置新 SelectedObject
之前和之后显示的属性数量,并执行 relative 滚动.
在这里,我通过 AccessibilityObject.Role
找到 PropertyGridView
,也就是 AccessibleRole.Table
,但您也可以通过其文本 ( "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);
}
我在 Windows Forms 应用程序中有一个 PropertyGrid
。每当它的 SelectedObject
发生变化时,它会将其 VerticalScroll
值重置为 0。我需要它保持原样。下面的代码似乎没有做任何事情。我已经尝试了 PerformLayout
和许多其他解决方案,但都没有成功。有什么想法吗?
int pos = MyGrid.VerticalScroll.Value;
MyGrid.SelectedObject = SomeDifferentObject;
MyGrid.VerticalScroll.Value = pos;
VerticalScroll
属性 与 PropertyGrid class 无关。它引用 VScrollBar
控件的内部属性。 Scroll 事件永远不会上升。
VScrollBar
是 System.Windows.Forms.PropertyGridInternal.PropertyGridView
控件的子控件,class 不能直接访问。
无论如何都可以得到它,将 PropertyGrid 转换为 Control 或忽略 PropertyGrid 的 Controls
属性 的 Browsable(false)
属性,然后找到 VScrollBar
子项,存储当前值然后在更改 SelectedObject
属性.
后再次设置它
请注意,这个新控件可以具有与以前不同数量的属性,滚动条将只设置在以前的位置。
为了更加 精确 ,您可以获得设置新 SelectedObject
之前和之后显示的属性数量,并执行 relative 滚动.
在这里,我通过 AccessibilityObject.Role
找到 PropertyGridView
,也就是 AccessibleRole.Table
,但您也可以通过其文本 ( "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);
}