从属性网格重置属性

发布于 2024-07-16 20:17:22 字数 482 浏览 11 评论 0原文

我正在使用 PropertyGrid 显示对象的属性。 但是,我还允许用户创建自己的属性,并为这些自定义属性设置值。 每个可以具有这些自定义属性的对象都有一个 Dictionary 集合,其中字符串是标识属性的唯一键,而 Object 是基本类型(字符串、布尔、int 等)的值。

我创建了一个自定义PropertyDescriptor 具有 get 和 set 方法,用于检查字典中是否有匹配的键,或者分别使用匹配的键创建/覆​​盖值。

但是,我还想让用户能够清除该属性,从而从字典中完全删除其条目。 我将代码放入自定义 PropertyDescriptor 的 ResetValue 重写方法中,但是我没有看到任何通过 PropertyGrid 接口来调用它的方法? 它似乎不是上下文菜单选项或类似的明显选项。

因此,如果我有一个带有自定义 ResetValue 方法的自定义 PropertyDescriptor,那么如何从 PropertyGrid 中实际调用该方法呢?

I am using a PropertyGrid to show properties from my objects. However, I'm also allowing the user to create their own properties, and set values for these custom properties. Each object that can have these custom properties has a Dictionary collection, where the string is a unique key to identify the property, and Object is the value of a primitive type (string, bool, int etc..)

I've created a custom PropertyDescriptor with get and set methods that check the Dictionary for a matching key, or create/overwrite the value with a matching key respectively.

However, I also want to give the user the ability to clear the property, and thus remove its entry from the dictionary entirely. I'd put the code to to this in the ResetValue override method of my custom PropertyDescriptor, however I don't see any way through the PropertyGrid interface to envoke this? It doesn't seem to be a context menu option or something obvious like that.

So if I have a custom PropertyDescriptor with a custom ResetValue method, how do I actually evoke that method from a PropertyGrid?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

深海蓝天 2024-07-23 20:17:22

我认为实现此目的的最简单方法是将上下文菜单添加到属性网格,其中包含菜单项“重置”,然后像这样处理其单击事件:

private void resetToolStripMenuItem_Click(object sender, EventArgs e)
{                        
    PropertyDescriptor pd = propGrid.SelectedGridItem.PropertyDescriptor;
    pd.ResetValue(propGrid.SelectedObject);
}

我认为 Visual Studio 会执行类似的操作。

I think the easiest way to achieve this is to add a contextmenu to your property grid, with a menu item "Reset", and then handling its click event like this:

private void resetToolStripMenuItem_Click(object sender, EventArgs e)
{                        
    PropertyDescriptor pd = propGrid.SelectedGridItem.PropertyDescriptor;
    pd.ResetValue(propGrid.SelectedObject);
}

I think Visual Studio does something like this.

陌上芳菲 2024-07-23 20:17:22

注解:
PropertyGrid.SelectedObject 在子对象中返回错误的值(组件)。
因此,CanResetValue 方法收到了不正确的组件。

我的解决方案:

private void OnContextMenuOpening(object sender, CancelEventArgs e)
{
  var lGrid = mCurrentControl as PropertyGrid;

  if (lGrid != null)
  {
    var lItem = lGrid.SelectedGridItem;

    // Für untergeordnete Eigenschaften kann nicht SelectedObject verwendet werden
    // Component ist eine interne Eigenschaft der Klasse System.Windows.Forms.PropertyGridInternal.GridEntry
    // ((System.Windows.Forms.PropertyGridInternal.GridEntry)(lItem)).Component
    // Zugriff via Reflection
    var lComponent = lItem.GetType().GetProperty("Component").GetValue(lItem, null);

    if (lComponent != null)
      tsmi_Reset.Enabled = lItem.PropertyDescriptor.CanResetValue(lComponent);
    else
      tsmi_Reset.Enabled = lItem.PropertyDescriptor.CanResetValue(lGrid.SelectedObject);
  }
}

// Contextmenu -> Reset
private void OnResetProperty(object sender, EventArgs e)
{
  var lGrid = mCurrentControl as PropertyGrid;

  if (lGrid != null)
    lGrid.ResetSelectedProperty();
}

Annotation:
The PropertyGrid.SelectedObject returns the wrong Value (component) in Childobjects.
Consequently the Method CanResetValue recived a incorrect component.

My Solution:

private void OnContextMenuOpening(object sender, CancelEventArgs e)
{
  var lGrid = mCurrentControl as PropertyGrid;

  if (lGrid != null)
  {
    var lItem = lGrid.SelectedGridItem;

    // Für untergeordnete Eigenschaften kann nicht SelectedObject verwendet werden
    // Component ist eine interne Eigenschaft der Klasse System.Windows.Forms.PropertyGridInternal.GridEntry
    // ((System.Windows.Forms.PropertyGridInternal.GridEntry)(lItem)).Component
    // Zugriff via Reflection
    var lComponent = lItem.GetType().GetProperty("Component").GetValue(lItem, null);

    if (lComponent != null)
      tsmi_Reset.Enabled = lItem.PropertyDescriptor.CanResetValue(lComponent);
    else
      tsmi_Reset.Enabled = lItem.PropertyDescriptor.CanResetValue(lGrid.SelectedObject);
  }
}

// Contextmenu -> Reset
private void OnResetProperty(object sender, EventArgs e)
{
  var lGrid = mCurrentControl as PropertyGrid;

  if (lGrid != null)
    lGrid.ResetSelectedProperty();
}
弱骨蛰伏 2024-07-23 20:17:22

对于子对象,对包含属性的对象的引用隐藏在 GridItem 类的非公共后代的 Instance 属性中。 值得庆幸的是,此属性是这些后代类实现的 ITypeDescriptorContext 接口的成员。 因此,有一个解决方案,包括在所有属性的上下文菜单中正确启用“重置”命令:

private void contextMenuToolStrip_Opening(object sender, CancelEventArgs e)
{
  var item = propertyGrid.SelectedGridItem;
  resetToolStripMenuItem.Enabled = item != null &&
                                   item.GridItemType == GridItemType.Property &&
                                   item is ITypeDescriptorContext context &&
                                   item.PropertyDescriptor.CanResetValue(context.Instance);
}

private void resetToolStripMenuItem_Click(object sender, EventArgs e)
{
  propertyGrid.ResetSelectedProperty();
}

For child objects the reference to the object containing a property is hidden in the Instance property of the non-public descendants of the GridItem class. Thankfully, this property is a member of the ITypeDescriptorContext interface which these descendant classes do implement. So, there is a solution that includes correct enabling of the Reset command in a context menu for all properties:

private void contextMenuToolStrip_Opening(object sender, CancelEventArgs e)
{
  var item = propertyGrid.SelectedGridItem;
  resetToolStripMenuItem.Enabled = item != null &&
                                   item.GridItemType == GridItemType.Property &&
                                   item is ITypeDescriptorContext context &&
                                   item.PropertyDescriptor.CanResetValue(context.Instance);
}

private void resetToolStripMenuItem_Click(object sender, EventArgs e)
{
  propertyGrid.ResetSelectedProperty();
}
梦途 2024-07-23 20:17:22

这就是我用来重置我的属性的方法

    public static void InitResetContextMenuStrip(this PropertyGrid grid, params string[] resettableProperties)
    {
        if (grid.ContextMenuStrip != null)
            return;

        var menuStrip = new ContextMenuStrip();
        var resetItem = new ToolStripMenuItem("Reset");

        resetItem.Click += (s, e) =>
        {
            try
            {
                if (resettableProperties.Any(p => grid.SelectedGridItem.PropertyDescriptor.Name == p))
                {
                    grid.SelectedGridItem.PropertyDescriptor.SetValue(grid.SelectedObject, null);
                    grid.Refresh(); //redraw the grid to reflect the changes
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        };

        menuStrip.Items.Add(resetItem);

        menuStrip.Opening += (s, e) =>
        {
            try
            {
                resetItem.Enabled = resettableProperties.Any(p => grid.SelectedGridItem.PropertyDescriptor.Name == p);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        };

        grid.ContextMenuStrip = menuStrip;
    }

这就是我使用它的方式:

myGrid.InitResetContextMenuStrip(
    nameof(ClassName.PropertyName1),
    nameof(ClassName.PropertyName2));

信用: http://www.windows-tech.info/3/41955b2a405bf481.php

This is what i am using to reset my properties

    public static void InitResetContextMenuStrip(this PropertyGrid grid, params string[] resettableProperties)
    {
        if (grid.ContextMenuStrip != null)
            return;

        var menuStrip = new ContextMenuStrip();
        var resetItem = new ToolStripMenuItem("Reset");

        resetItem.Click += (s, e) =>
        {
            try
            {
                if (resettableProperties.Any(p => grid.SelectedGridItem.PropertyDescriptor.Name == p))
                {
                    grid.SelectedGridItem.PropertyDescriptor.SetValue(grid.SelectedObject, null);
                    grid.Refresh(); //redraw the grid to reflect the changes
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        };

        menuStrip.Items.Add(resetItem);

        menuStrip.Opening += (s, e) =>
        {
            try
            {
                resetItem.Enabled = resettableProperties.Any(p => grid.SelectedGridItem.PropertyDescriptor.Name == p);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        };

        grid.ContextMenuStrip = menuStrip;
    }

And this is how i use it:

myGrid.InitResetContextMenuStrip(
    nameof(ClassName.PropertyName1),
    nameof(ClassName.PropertyName2));

Credit: http://www.windows-tech.info/3/41955b2a405bf481.php

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文