Pergunta

Estou criando um formulário de "seletor de departamento" que servirá como uma forma pop -up modal com muitas das minhas formas "primárias" de um aplicativo Winforms. Idealmente, o usuário clicará em um ícone ao lado de uma caixa de texto que exibirá o formulário, eles selecionarão o departamento de que precisam e, quando clicarem em OK, a caixa de diálogo fechará e eu terei o valor selecionado para mim para que eu Atualize a caixa de texto com.

Eu já fiz a rota com a passagem do proprietário da caixa de diálogo para o formulário de diálogo e ter o evento OK Button Click, faça a atualização adequada, mas isso me obriga a fazer um Directcast para o tipo de formulário e só posso reutilizar o Picker no formulário atual.

Consegui usar uma variável BYREF no construtor e atualizar com sucesso um valor, mas funciona apenas no construtor. Se eu tentar atribuir o valor BYRef a alguma variável interna na aula de seleção do departamento, perco o aspecto de referência dela. Este é o meu código básico anexado ao meu formulário:

Public Class DeptPicker

   Private m_TargetResult As String

   Public Sub New(ByRef TargetResult As String)

      InitializeComponent()

      ' This works just fine, my "parent" form has the reference value properly updated.
      TargetResult = "Booyah!"

      ' Once I leave the constructor, m_TargetResult is a simple string value that won't update the parent
      m_TargetResult = TargetResult

   End Sub

   Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click

      DialogResult = Windows.Forms.DialogResult.OK

      ' I get no love here. m_TargetResult is just a string and doesn't push the value back to the referenced variable I want.
      m_TargetResult = "That department I selected."
      Me.Close()

   End Sub

   Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click

      DialogResult = Windows.Forms.DialogResult.Cancel
      Me.Close()

   End Sub

End Class

Alguém pode me dizer o que estou perdendo aqui ou uma abordagem diferente para fazer isso acontecer?

NOTA: O exemplo de código está no vb.net, mas também aceitarei as respostas C#. 8^d

Foi útil?

Solução

Nesses casos, eu geralmente também

  • Escreva uma função ShowDialog que faça o que eu quero (por exemplo, retorne o valor) ou
  • Apenas deixe o resultado ser uma propriedade na caixa de diálogo. É assim que as caixas de diálogo comuns de arquivo fazem isso no BCL. O chamador deve então ler a propriedade para obter o resultado. Tudo bem na minha opinião.

Você também pode combinar esses métodos, tornando o valor do resultado uma propriedade na caixa de diálogo e criando um método ShowDialog que retorna esse valor de propriedade, como Byref que desejar ou como um valor de retorno, dependendo de suas necessidades.

Vou adicionar isso como uma instrução de uso, por exemplo (desculpe, nenhum VB aqui, e você disse que C# é bem -vindo):

using (var dlg = new DeptPicker()) {
    if (dlg.ShowDialog() == DialogResult.OK) {
        myTextBoxOrWhatEver.Text = dlg.TargetResult;
    }
}

Na própria caixa de diálogo, basta fazer isso:

void okButton_Click(object sender, EventArgs e)
{
    TargetResult = whatever; // can also do this when the selection changes
    DialogResult = DialogResult.OK;
    Close();
}

Eu não usei a nova implementação do showDialog nesta amostra.

Outras dicas

O problema é que a atribuição de TargetResult no construtor está usando a string como referência. A sequência M_TARGETRESULT é apenas uma cópia da string ref, não uma referência à string original.

Quanto a como fazer um "ponteiro" para o original, eu não sei.

Isso é ainda mais difícil pelo fato de o vb.net não suportar blocos de código inseguros, para que você não possa fazer uma referência de ponteiro à string.

Você pode passar na referência da caixa de texto para o formulário modal.

Deixe o usuário escolher qualquer departamento. Quando o usuário clicar OK, defina a propriedade de texto da caixa de texto referida como o texto ou o ID do departamento escolhido (depende do que você precisa)

Estou usando o código fornecido por você.


Public Class DeptPicker

   Private m_TargetTextBox As TextBox

   Public Sub New(ByRef TargetTextBox As TextBox)
      InitializeComponent()

      m_TargetTextBox = TargetTextBox

   End Sub

   Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click

      DialogResult = Windows.Forms.DialogResult.OK

      ' I get no love here. m_TargetResult is just a string and doesn't push the value back to the referenced variable I want.
      m_TargetTextBox.Text = "That department I selected."
      Me.Close()

   End Sub

   Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click

      DialogResult = Windows.Forms.DialogResult.Cancel
      Me.Close()

   End Sub

End Class


Public Class DeptPicker

    dim dlgResult as DialogResult

    Public Function GetSelectedDepartment() As String
        Me.Show vbModal
        If (dlgResult = Windows.Forms.DialogResult.OK) Then
            return "selected department string here"
        Else
            return "sorry, you didnt canceled on the form"
        End If
    End Function

    Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
        dlgResult = Windows.Forms.DialogResult.OK
        Me.Close()
    End Sub

    Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        dlgResult = Windows.Forms.DialogResult.Cancel
        Me.Close()
    End Sub
End Class

Nota: Eu não testei isso. Espero que você tenha uma ideia do que quero dizer.

Oregonghost: Isso parece melhor?

O usuário pode ligar para o novo deptpicker (). GetSelectedDepartment (). Eu não sabia que não preciso postar a resposta novamente e poderia usar a mesma postagem.

Obrigado Oregonghost. Agora, parece bem?

Isso pode funcionar:

    // This code in your dialog form.  Hide the base showdialog method 
    // and implement your own versions
    public new string ShowDialog() {
        return this.ShowDialog(null);
    }

    public new string ShowDialog(IWin32Window owner) {
        // Call the base implementation of show dialog
        base.ShowDialog(owner);

        // You get here after the close button is clicked and the form is hidden.  Capture the data you want.
        string s = this.someControl.Text;

        // Now really close the form and return the value
        this.Close();
        return s;
    }

    // On close, just hide.  Close in the show dialog method
    private void closeButton_Click(object sender, EventArgs e) {
        this.Hide();
    }

    // This code in your calling form
    MyCustomForm f = new MyCustomForm();
    string myAnswer = f.ShowDialog();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top