Pergunta

Eu estou usando um PropertyGrid para mostrar as propriedades dos meus objetos. No entanto, eu também estou permitindo que o usuário crie suas próprias propriedades e valores definidos para estas propriedades personalizadas. Cada objeto que pode ter estas propriedades personalizadas tem uma coleção Dictionary, onde a corda é uma chave única para identificar a propriedade e objeto é o valor de um tipo primitivo (string, bool, int etc ..)

Eu criei um PropertyDescriptor personalizado com métodos get e set que verificam o dicionário para uma chave correspondente, ou criar / substituir o valor com uma chave correspondente, respectivamente.

No entanto, eu também quero dar ao usuário a capacidade de limpar a propriedade e, portanto, remover a entrada do dicionário completo. Eu ia colocar o código para a isso no método de substituição ResetValue da minha PropertyDescriptor personalizado, no entanto, não vejo qualquer maneira através da interface PropertyGrid para envoke isso? Não parece ser uma opção do menu de contexto ou algo óbvio assim.

Então, se eu tenho um PropertyDescriptor personalizado com um método ResetValue costume, como eu realmente evocar esse método a partir de um PropertyGrid?

Foi útil?

Solução

Eu acho que a maneira mais fácil de conseguir isso é para adicionar um contextmenu à sua grade de propriedade, com um item de menu "Reset", e então lidar com seu evento de clique como esta:

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

Eu acho que Visual Studio faz algo parecido com isto.

Outras dicas

Anotação: O PropertyGrid.SelectedObject retorna o valor errado (componente) no Childobjects. Consequentemente, o método CanResetValue recived um componente incorreto.

Meu Solução:

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

Para objetos filho a referência para o objeto que contém uma propriedade está escondido na propriedade Instance dos descendentes não-públicos da classe GridItem. Felizmente, esta propriedade é um membro da interface ITypeDescriptorContext que essas classes descendentes não implementar. Assim, não há uma solução que inclui correta habilitação do comando Repor em um menu de contexto para todas as propriedades:

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();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top