Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在特性网格中选择特性_C#_Propertygrid - Fatal编程技术网

C# 在特性网格中选择特性

C# 在特性网格中选择特性,c#,propertygrid,C#,Propertygrid,我正在使用PropertyGrid向用户显示对象的内容 假设单元格值与属性值匹配,则此PropertyGrid与Excel工作表同步 当用户在PropertyGrid中选择一个属性时,应用程序会高亮显示旁边打开的Excel工作表中相应的单元格。我可以使用SelectedGridItemChanged事件执行此操作 现在,当用户在Excel工作表中选择单元格时,我希望在我的PropertyGrid中选择一个属性 void myWorkbook_SheetSelectionChangeEvent(N

我正在使用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可以写入

不幸的是,我没有找到访问PropertyGrid的GridItems集合的方法,因此我可以查找正确的GridItem并选择它


如何执行此操作?

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

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

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

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

我在一个项目中遇到了这个问题,所以我为它编写了一个扩展方法:

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;
}
下面是一个扩展方法,其中包含一个私有的支持方法,用于遍历对象层次结构(如果适用于对象模型):

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

我在一个项目中遇到了这个问题,所以我为它编写了一个扩展方法:

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;
}
下面是一个扩展方法,其中包含一个私有的支持方法,用于遍历对象层次结构(如果适用于对象模型):

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

我看了上面的选项,不太喜欢它们,我稍微修改了一下,发现这对我来说很好

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。如果其中一个是匹配项,则返回true。这可能不是您想要的,因此请更新该项

在我的用例中,我需要根据用户可以选择的值来选择属性,以便像这样调用上述方法:

if (TryFindGridItem(pgMain, propertyName, out GridItem gridItem))
{                
     gridItem.Select();
}
理论上,除非用户选择一个不合适的字符串,否则它永远不会找到它。通过这种方式,可以使用else更新if。。我宁愿保证它的安全,如果找不到指定的名称,就会出现空指针异常

此外,我不会讨论子类和类列表,因为我的用例不需要这些,如果您的用例需要的话,那么可能会在GridItem中进行递归调用


请注意,将GridItem替换为var,代码在编译时停止。IDE不知道GridItemCollection返回什么…

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

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。如果其中一个是匹配项,则返回true。这可能不是您想要的,因此请更新该项

在我的用例中,我需要根据用户可以选择的值来选择属性,以便像这样调用上述方法:

if (TryFindGridItem(pgMain, propertyName, out GridItem gridItem))
{                
     gridItem.Select();
}
理论上,除非用户选择一个不合适的字符串,否则它永远不会找到它。通过这种方式,可以使用else更新if。。我宁愿保证它的安全,如果找不到指定的名称,就会出现空指针异常

此外,我不会讨论子类和类列表,因为我的用例不需要这些,如果您的用例需要的话,那么可能会在GridItem中进行递归调用


请注意,用var替换GridItem,代码在编译时停止,IDE不知道GridItemCollection返回什么…

。。。然后我可以使用PropertyDescriptor属性来获取我想要的GridItem,然后我可以进行选择。要是我能投两次票就好了。。。我唯一的怪癖是我的PropertyGrid有时是空的,所以在应用它之前,我必须检查是否选择了GridItem。明亮的非常感谢你。的确顺便说一句,欢迎来到SO社区。。。。然后我可以使用PropertyDescriptor属性来获取我想要的GridItem,然后我可以进行选择。要是我能投两次票就好了。。。我唯一的怪癖是我的PropertyGrid有时是空的,所以在应用它之前,我必须检查是否选择了GridItem。明亮的非常感谢你。的确顺便说一句,欢迎来到SO社区。