Вопрос

Я использую PropertyGrid для отображения свойств моих объектов.Однако я также разрешаю пользователю создавать свои собственные свойства и устанавливать значения для этих настраиваемых свойств.Каждый объект, который может иметь эти настраиваемые свойства, имеет коллекцию Dictionary, где строка — это уникальный ключ для идентификации свойства, а Object — это значение примитивного типа (string, bool, int и т. д.).

Я создал собственный PropertyDescriptor с методами get и set, которые проверяют словарь на наличие соответствующего ключа или создают/перезаписывают значение соответствующим ключом соответственно.

Однако я также хочу дать пользователю возможность очистить свойство и, таким образом, полностью удалить его запись из словаря.Я бы поместил код для этого в метод переопределения ResetValue моего пользовательского PropertyDescriptor, однако я не вижу никакого способа через интерфейс PropertyGrid вызвать это?Кажется, это не опция контекстного меню или что-то очевидное в этом роде.

Итак, если у меня есть собственный PropertyDescriptor с собственным методом ResetValue, как мне на самом деле вызвать этот метод из PropertyGrid?

Это было полезно?

Решение

Я думаю, что самый простой способ добиться этого — добавить контекстное меню в сетку свойств с пунктом меню «Сброс», а затем обработать событие щелчка следующим образом:

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

Я думаю, что Visual Studio делает что-то подобное.

Другие советы

Аннотация: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();
}

Для дочерних объектов ссылка на объект, содержащий свойство, скрыта в Instance имущество негосударственных потомков GridItem сорт.К счастью, этот объект размещения является членом 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();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top