简体   繁体   中英

Refer to RadioButton_Checkedchanged value from another form

I'm writing a little program that should handle conversion between CSV and XML and from XML to TXT. In the main form I've inserted two radio buttons that the user will click to start the desired conversion.

So far I have to .cs files: MainForm.cs and ConversionForm.cs.

In MainForm.cs I have declared MainForm as static to give ConversionForm access to its methods.

    public MainForm()
    {
        InitializeComponent();
    }

    public static MainForm mform = null;

... Then I inserted the functions for the event handler that checks the change:

    public void CSVConversionRadio_CheckedChanged(object sender, EventArgs e)
    {
        this.CSVConversionRadio.Checked = true;
    }

    public void TXTConversionRadio_CheckedChanged(object sender, EventArgs e)
    {
        this.TXTConversionRadio.Checked = true;
    }

...

In ConversionForm I have a "Convert" button that should handle the conversion based on the user's input choice.

    public void conversionButton_Click(object sender, EventArgs e)
    {

        if (MainForm.mform.CSVConversionRadio.Checked = true)
        {
            CSVConversion();
        }

        if (MainForm.mform.TXTConversionRadio.Checked = true)
        {
            TXTConversion();
        }
    }

The problem I'm facing is that when the function checks the state of the radio buttons, the program returns "null", throwing an exception. Before doing some changes to the code, that is, declaring the static function

public static MainForm mform = null;

MainForm.mform.CSVConversionRadio.Checked was always returning a status of "false", probably because a new form (Conversion) was being instantiated and the event handler reset their state to the default.

So, here are my questions:

  1. How can I pass the current value of the radio buttons to the Conversion Form, allowing the conversion functions to execute according to the user's choice?

  2. Generally, how can i reference properties, methods and fields from another form, without creating a new instance, but only pointing to the previous one still opened?

There are several ways of sharing information between forms.

I think an easy way for you is to have a mediator class that both forms are aware of.

public class ConversionContext : INotifyPropertyChanged {
    private ConversionType type;

    public ConversionType Type {
        get { return type; }
        set {
            if (type != value) {
                type = value;
                onPropertyChanged("ConversionType");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void onPropertyChanged(string propertyName) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public enum ConversionType { None, Xls, Csv, Txt }

Then, when you're creating your forms, you pass an instance of the same ConversionContext to them, using either a constructor or properties on both forms. If you're using a property, this is how it can be done.

private ConversionContext context;
public ConversionContext SharedContext {
   get { return context; }
   set {
       if (context == value) {
          return;
       }
       if (context != null) {
           context.PropertyChanged -= onContextPropertyChanged;
       }
       context = value;
       context.PropertyChanged += onContextPropertyChanged;
   }
}

In your main form you can add an event handler for when the user checks a control that sets this type.

public void CSVConversionRadio_CheckedChanged(object sender, EventArgs e)
{
    context.Type = ConversionType.Csv;
}

When setting the type, the PropertyChanged event is triggered, that you can pick up on and respond to in your forms.

private void onContextPropertyChanged(object sender, PropertyChangedEventArgs e) {
     switch (context.Type) {
         case ConversionType.Xls :
              // check a checkbox that represents xls
         break;
         // handle the other file types
     }
}

And when pressing the button in your ConversionForm, the type is set

public void conversionButton_Click(object sender, EventArgs e) {
    switch (context.Type) {
        case ConversionType.Csv:
            CSVConversion();
            break;
        case ConversionType.Txt:
            TXTConversion();
            break;
    }
}

This also reduces the dependencies between the forms, leading to looser coupling between the two.

Throw away that static variable mform. Is of no use if you leave at null value.
Instead when you call the constructor of ConversionForm from MainForm pass the instance of MainForm to the instance of ConversionForm

ConversionForm conv = new ConversionForm(this);

then in the constructor of ConversionForm save the instance passed in a global variable

public partical class ConversionForm:Form
{
    MainForm _currentInstanceMainForm = null
    public ConversionFomr(MainForm f)
    {
        _currentInstanceMainForm = f;
    }
}

now when you need to call public methods of MainForm you could use the instance passed at contruction time

public void conversionButton_Click(object sender, EventArgs e)
{
    if (_currentInstanceMainForm.CSVConversionRadio.Checked == true)
    {
        CSVConversion();
    }

    if (currentInstanceMainForm.TXTConversionRadio.Checked == true)
    {
        TXTConversion();
    }
}

However It is better to isolate the internal controls of MainForm and never let an external form access directly the controls of MainForm.
To allow this pattern you need to prepare two public properties that every external form could check to get information on the state of MainForm controls

in MainForm add these two public properties

 public bool CSVConversionRequired
 {
     get { return (this.CSVConversionRadio.Checked); }
 }

 public bool TXTConversionRequired
 {
     get { return (this.TXTConversionRadio.Checked); }
 }

and change the ConversionForm to

public void conversionButton_Click(object sender, EventArgs e)
{
    if (_currentInstanceMainForm.CSVConversionRequired == true)
        CSVConversion();

    if (currentInstanceMainForm.TXTConversionRequired == true)
    {
        TXTConversion();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM