在属性网格中选择一个属性

时间:2013-12-03 14:43:09

标签: c# propertygrid

我正在使用PropertyGrid向用户显示对象的内容。

假设单元格值与属性值匹配,此PropertyGrid将与Excel工作表同步。

当用户在PropertyGrid中选择一个属性时,应用程序会突出显示旁边打开的Excel工作表中的相应单元格。我可以使用SelectedGridItemChanged事件来执行此操作。

现在,当用户在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--;
    }
}

我注意到SelectedGridItem可以写入。

很遗憾,我找不到访问GridItems PropertyGrid集合的方法,因此我可以找到正确的GridItem并选择它。

我该怎么做?

3 个答案:

答案 0 :(得分:1)

您可以从根目录获取所有GridItem。我使用以下代码检索属性网格中的所有网格项

private GridItem Root
    {
        get
        {
            GridItem aRoot = myPropertyGrid.SelectedGridItem;
            do
            {
                aRoot = aRoot.Parent ?? aRoot;
            } while (aRoot.Parent != null);
            return aRoot;
        }
    }

并将根传递给下面的方法

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

答案 1 :(得分:0)

我反对这个项目,所以我为它写了一个扩展方法:

xaxis.setLabelCount(4, force: true)

这是一个扩展方法,它带有一个私有的支持方法,用于遍历对象的层次结构(如果这适用于您的对象模型):

<ul>
<li>
<input type="radio" id="f-option" name="gender">
<label for="f-option" class="gender female"><img src="images/52x42.png"></label>
<div class="check"></div>
</li>
</ul>

答案 2 :(得分:0)

我查看了上述选项,但并不太喜欢它们,我对其进行了一些更改,发现这对我来说很有效

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

它使用一个名为match的本地方法,如果您使用的是C#版本,则只需将其放在该方法的外部即可,也许可以给它一个更好的名称。

Match会查看DisplayName以及属性名称,如果其中一个匹配,则返回true,这可能不是您想要的,所以请对其进行更新。

在我的用例中,我需要根据用户可以选择的值来选择属性,因此调用上述方法如下:

if (TryFindGridItem(pgMain, propertyName, out GridItem gridItem))
{                
     gridItem.Select();
}

理论上它永远不会找到它,除非用户选择了一个不合适的字符串,否则if可以使用else进行更新..我宁愿保持它的安全,如果找不到则有一个null指针异常指定的名称。

我也不打算进入子类和类列表,因为我的用例不需要它,如果您需要的话,也许可以在GridItem中进行递归调用。

小提示,将 GridItem 替换为 var ,并且代码制动,因为在编译时IDE不知道GridItemCollection返回什么……