كيف يمكنني الاحتفاظ بمتغير ByRef في نموذج حوار .net winforms؟

StackOverflow https://stackoverflow.com/questions/150010

سؤال

أقوم بإنشاء نموذج "منتقي القسم" الذي سيكون بمثابة نموذج منبثق مشروط مع العديد من النماذج "الأساسية" لتطبيق Winforms.من الناحية المثالية، سيقوم المستخدم بالنقر فوق أيقونة بجوار مربع النص الذي سينبثق النموذج، وسيقوم بتحديد القسم الذي يحتاجه، وعندما ينقر فوق "موافق"، سيتم إغلاق مربع الحوار وسيتم تحديد القيمة لي قم بتحديث مربع النص باستخدام.

لقد قمت بالفعل بالتوجيه بتمرير مالك مربع الحوار إلى نموذج الحوار وجعل حدث النقر فوق الزر "موافق" يقوم بالتحديث المناسب، ولكن هذا يجبرني على إجراء DirectCast لنوع النموذج ولا يمكنني بعد ذلك سوى إعادة استخدام منتقي في النموذج الحالي.

لقد تمكنت من استخدام متغير ByRef في المنشئ وتحديث القيمة بنجاح، ولكنه يعمل فقط في المنشئ.إذا حاولت تعيين قيمة ByRef لبعض المتغيرات الداخلية في فئة منتقي الأقسام، فسوف أفقد الجانب المرجعي منها.هذا هو الكود الأساسي المرفق بالنموذج الخاص بي:

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

هل يمكن لأحد أن يخبرني ما الذي أفتقده هنا أو طريقة مختلفة لتحقيق ذلك؟

ملحوظة:نموذج التعليمات البرمجية موجود في VB.NET، لكنني سأتلقى أي إجابات C# أيضًا.8 ^ د

هل كانت مفيدة؟

المحلول

في مثل هذه الحالات، أنا عادة إما

  • اكتب وظيفة ShowDialog التي تفعل ما أريد (على سبيل المثال.إرجاع القيمة) أو
  • فقط دع النتيجة تكون خاصية في مربع الحوار.هذه هي الطريقة التي تقوم بها مربعات حوار الملفات الشائعة في BCL.يجب على المتصل بعد ذلك قراءة الخاصية للحصول على النتيجة.هذا جيد في رأيي.

يمكنك أيضًا دمج هذه الأساليب، عن طريق جعل القيمة الناتجة خاصية في مربع الحوار وإنشاء أسلوب ShowDialog الذي يُرجع قيمة الخاصية تلك، إما كـ ByRef كما تريد أو كقيمة إرجاع، وفقًا لاحتياجاتك.

سأضيف هذا كتعليمات استخدام، على سبيل المثال (عذرًا، لا يوجد VB هنا، وقد قلت أن C# مرحب به):

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

في مربع الحوار نفسه، فقط قم بما يلي:

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

بالرغم من ذلك، لم أستخدم تطبيق ShowDialog الجديد في هذه العينة.

نصائح أخرى

تكمن المشكلة في أن تعيين TargetResult في المُنشئ يستخدم السلسلة كمرجع.سلسلة m_TargetResult هي مجرد نسخة من سلسلة المرجع، وليست مرجعًا للسلسلة الأصلية.

أما بالنسبة لكيفية عمل "مؤشر" للأصل فلا أعرف.

ومما يزيد من صعوبة ذلك حقيقة أن VB.NET لا يدعم كتل التعليمات البرمجية غير الآمنة، لذلك لا يمكنك إنشاء مرجع للسلسلة.

يمكنك تمرير مرجع مربع النص إلى النموذج المشروط.

السماح للمستخدم باختيار أي قسم.عندما ينقر المستخدم على "موافق"، قم بتعيين خاصية النص الخاصة بمربع النص المشار إليه على نص أو معرف القسم المختار (يعتمد على ما تحتاجه)

أنا أستخدم الكود الذي قدمته.


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

ملحوظة:لم أختبر هذا.أتمنى أن تكون قد حصلت على فكرة عما أقصده.

شبح أوريغون:هل يبدو هذا أفضل؟

يمكن للمستخدم استدعاء DeptPicker().GetSelectedDepartment() الجديد.لم أكن أعلم أنني لست بحاجة إلى نشر الإجابة مرة أخرى ويمكنني استخدام نفس المنشور.

شكرا أوريجون جوست.الآن، هل يبدو الأمر على ما يرام؟

قد ينجح هذا:

    // 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();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top