[英]Select a property in the property grid
I am using a PropertyGrid
to display the content of an object to the user. 我正在使用
PropertyGrid
向用户显示对象的内容。
This PropertyGrid
is synchronized with an Excel sheet, assuming a cell value match a property value. 假定单元格值与属性值匹配,则此
PropertyGrid
与Excel工作表同步。
As the user selects a property in the PropertyGrid
, the application highlights the corresponding cell in the Excel sheet which is opened beside. 当用户在
PropertyGrid
选择PropertyGrid
,应用程序将突出显示旁边打开的Excel工作表中的相应单元格。 I can do this using the SelectedGridItemChanged
event. 我可以使用
SelectedGridItemChanged
事件来做到这一点。
Now, I want to have a property selected in my PropertyGrid when the user selects a cell in the Excel sheet. 现在,当用户在Excel工作表中选择一个单元格时,我想在PropertyGrid中选择一个属性 。
void myWorkbook_SheetSelectionChangeEvent(NetOffice.COMObject Sh, Excel.Range Target)
{
if (eventMask > 0)
return;
try
{
eventMask++;
this.Invoke(new Action(() =>
{
propertyGrid1.SelectedGridItem = ... // ?
}
}
finally
{
eventMask--;
}
}
I noticed that the SelectedGridItem
can be written to. 我注意到
SelectedGridItem
可以写入。
Unfortunately I do not find a way to access the GridItems
collection of my PropertyGrid
so I can look for the right GridItem and select it. 不幸的是,我找不到访问我的
PropertyGrid
的GridItems
集合的方法,因此我可以寻找合适的GridItem并将其选中。
How can I do this? 我怎样才能做到这一点?
You can get all the GridItems from the root. 您可以从根目录获取所有GridItems。 I am using the below code to retrieve all the griditems within a property grid
我正在使用下面的代码来检索属性网格内的所有网格项
private GridItem Root
{
get
{
GridItem aRoot = myPropertyGrid.SelectedGridItem;
do
{
aRoot = aRoot.Parent ?? aRoot;
} while (aRoot.Parent != null);
return aRoot;
}
}
and pass the root to the below method 并将根传递给以下方法
private IList<GridItem> GetAllChildGridItems(GridItem theParent)
{
List<GridItem> aGridItems = new List<GridItem>();
foreach (GridItem aItem in theParent.GridItems)
{
aGridItems.Add(aItem);
if (aItem.GridItems.Count > 0)
{
aGridItems.AddRange(GetAllChildGridItems(aItem));
}
}
return aGridItems;
}
I came up against this quite a bit a project so I wrote an extension method for it: 我碰到了一个相当多的项目,因此为它编写了一个扩展方法:
if (!SetupManagerSettings.BootStrapperLocation.IsFile()) // Just another extension method to check if its a file
{
settingsToolStripMenuItem.Checked = true; // Event handler OnChecked ensures the settings panel is unhidden
settingsPropertyGrid.ActivateControl();
settingsPropertyGrid.SelectPropertyGridItemByName("BootStrapperLocation"); // Here is the extension method
return false;
}
Here is the extension method with a private, supporting method for traversing the hierarchy of objects (if this applies to your object model): 这是带有私有支持方法的扩展方法,用于遍历对象的层次结构(如果这适用于您的对象模型):
public static bool SelectPropertyGridItemByName(this PropertyGrid propertyGrid, string propertyName)
{
MethodInfo getPropEntriesMethod = propertyGrid.GetType().GetMethod("GetPropEntries", BindingFlags.NonPublic | BindingFlags.Instance);
Debug.Assert(getPropEntriesMethod != null, @"GetPropEntries by reflection is still valid in .NET 4.6.1 ");
GridItemCollection gridItemCollection = (GridItemCollection)getPropEntriesMethod.Invoke(propertyGrid, null);
GridItem gridItem = TraverseGridItems(gridItemCollection, propertyName);
if (gridItem == null)
{
return false;
}
propertyGrid.SelectedGridItem = gridItem;
return true;
}
private static GridItem TraverseGridItems(IEnumerable parentGridItemCollection, string propertyName)
{
foreach (GridItem gridItem in parentGridItemCollection)
{
if (gridItem.Label != null && gridItem.Label.Equals(propertyName, StringComparison.OrdinalIgnoreCase))
{
return gridItem;
}
if (gridItem.GridItems == null)
{
continue;
}
GridItem childGridItem = TraverseGridItems(gridItem.GridItems, propertyName);
if (childGridItem != null)
{
return childGridItem;
}
}
return null;
}
I looked at the above options and did not like them that much, I altered it a bit found that this works well for me 我查看了上述选项,但并不太喜欢它们,我对其进行了一些更改,发现这对我来说很有效
bool TryFindGridItem(PropertyGrid grid, string propertyName, out GridItem discover)
{
if (grid is null)
{
throw new ArgumentNullException(nameof(grid));
}
if (string.IsNullOrEmpty(propertyName))
{
throw new ArgumentException("You need to provide a property name", nameof(propertyName));
}
discover = null;
var root = pgTrainResult.SelectedGridItem;
while (root.Parent != null)
root = root.Parent;
foreach (GridItem item in root.GridItems)
{
//let's not find the category labels
if (item.GridItemType!=GridItemType.Category)
{
if (match(item, propertyName))
{
discover= item;
return true;
}
}
//loop over sub items in case the property is a group
foreach (GridItem child in item.GridItems)
{
if (match(child, propertyName))
{
discover= child;
return true;
}
}
//match based on the property name or the DisplayName if set by the user
static bool match(GridItem item, string name)
=> item.PropertyDescriptor.Name.Equals(name, StringComparison.Ordinal) || item.Label.Equals(name, StringComparison.Ordinal);
}
return false;
}
it uses a local method named match, if you're version of C# does not allow it then just put it external to the method and perhaps give it a better name. 它使用一个名为match的本地方法,如果您使用的C#版本不允许使用它,则只需将其放在该方法的外部即可,也许可以给它起一个更好的名称。
Match looks at the DisplayName as well as the property name and returns true if either is a match, this might not be what you would like so then update that. Match会查看DisplayName以及属性名称,如果其中一个匹配,则返回true,这可能不是您想要的,因此请对其进行更新。
In my usecase I need to select the property based on a value the user can select so call the above method like this: 在我的用例中,我需要根据用户可以选择的值来选择属性,因此调用上述方法如下:
if (TryFindGridItem(pgMain, propertyName, out GridItem gridItem))
{
gridItem.Select();
}
It could theoretically never not find it unless the user selects a string that is not proper this way the if can be updated using an else .. I rather keep it safe then have a null-pointer exception if I can't find the name specified. 从理论上讲,除非用户选择了不合适的字符串,否则无法找到它,否则可以使用else来更新if ..我宁愿保持它的安全,如果找不到指定的名称,则会出现null指针异常。
Also I am not going into sub classes and lists of classes as my use case doesn't need that, if yours does than perhaps make recursive calls in the GridItem. 另外,我不打算进入子类和类列表,因为用例不需要它,如果您的用例不需要,则可以在GridItem中进行递归调用。
Small note, replace GridItem with var and the code brakes as at compile time the IDE has no clue what a GridItemCollection returns… 请注意,用var替换GridItem并代码制动,因为在编译时IDE并不知道GridItemCollection返回什么…
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.