Pregunta

I have a program that has a parent form which then creates a child form. Upon clicking the updateButton within the child form, I want the searchButton within the parent form to fire.

However I get an error for protection reasons. I have tried setting everything Public just to see, still wont work for me.

Error 1 'SalesSystem.SystemForm.searchButton' is inaccessible due to its protection level SalesSystem\UpdateForm.cs 111 20 SalesSystem

This is what I have so far.

Parent Code

namespace SalesSystem
{
    public partial class SystemForm : Form
    {
        public SystemForm()
        {
            InitializeComponent();
        }    

        protected void searchButton_Click(object sender, EventArgs e)
        {
           //search code
        }

        private void updateButton_Click(object sender, EventArgs e)
        {
            try
            {
                UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text,            dbdirec, dbfname);
                upForm.ShowDialog(this);
            }
            catch (Exception)
            {
                //
            }
        }
    }

Child Code

namespace SalesSystem
{
    public partial class UpdateForm : Form
    {
        public UpdateForm(string selectedPerson, string dbdirec, string dbfname)
        {
            InitializeComponent();

        }

        private void updateButton_Click(object sender, EventArgs e)
        {
            //do stuff

            SystemForm parent = (SystemForm)this.Owner;
            parent.searchButton.PerformClick();

            this.Close();
        }
    }
}
¿Fue útil?

Solución

Your searchButton button control is set to private by default in WinForm. You've said you set everything to public but I assume you mean you've set everything in the code you've posted to public. There are a few ways to fix this. The direct fix would be to simply go to Visual Studio designer, select the button, and set its Modifier property to internal or public.

However, it seems you're closing your form straight after so I'd just have my parent form subscribe to the FormClosing event of the form.

UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.FormClosing += (s, o) =>
      {
          //your code for what the parent class should do
      };
upForm.ShowDialog(this);

If you're not closing the form then you can create your own event handler that your parent form subscribes to.

Otros consejos

You have 2 options:

  • create a public void search() method in your parent form. Then, instead of accessing the the button on the parent form and invoking its click event, you run the search code directly. The new method is not tied to a GUI element and accessing it from a different form is no problem.

  • The better solution is to create a delegate. A delegate is an execution target that will be assigned at run time. The parent form still has a public void search() method. And when it creates the child form, it will pass the name of that function as parameter. The child form has no knowledge about the parent form (as opposed to the first option where the child MUST know that there is a method called search()). When it is time to inform whoever created the child form, the delegate is called. This is a small example:

    public partial class SystemForm : Form
    {
        public delegate void dSearch();
    
        public SystemForm()
        {
            InitializeComponent();
        }
    
        protected void searchButton_Click(object sender, EventArgs e)
        {
            search();
        }
    
        private void search()
        {
            //search code
        }
    
        private void updateButton_Click(object sender, EventArgs e)
        {
            try
            {
                UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname, search);
                upForm.ShowDialog(this);
            }
            catch (Exception)
            {
                //
            }
        }
    }
    

And the child form:

public partial class UpdateForm : Form
{
    private SystemForm.dSearch _target;

    public UpdateForm(string selectedPerson, string dbdirec, string dbfname, SystemForm.dSearch target)
    {
        _target = target;
        InitializeComponent();
    }

    private void updateButton_Click(object sender, EventArgs e)
    {
        //do stuff
        _target();

        this.Close();
    }
}

You should use the "Model View Controller" or "Model View Presenter" pattern to approach this kind of thing.

Each form should only be concerned with displaying its contents to the user. When it comes to responding to UI events such as button clicks, each form (i.e. each "View") should simply raise an event which informs the controller/presenter that something has happened.

The controller/presenter should then respond appropriately. Then the logic that wires together different forms (such as the parent and child forms in your example) is encapsulated in the Controller class. Such logic does not really belong in either of the forms.

I wrote an example that demonstrates a simple design to do this sort of thing in another answer some time ago. Rather than copy/paste it all here, I'll just give you a link to it:

How to make Form1 label.text change when checkbox on form2 is checked?

You'll have to scroll down to see my answer. It's broadly similar to what you're doing; hopefully it will make sense to you! Follow the instructions to make a test application and run it to see what happens.

I'm tired and might be missing something but that is correct behaviour.

Your child form does not directly inherit from your parent form.

Your parent form has a protected level, so only it and classes that extend it can access the method.

2 solutions:

  1. Change your child form to:

public partial class UpdateForm : SystemForm

  1. Change method to public

public void searchButton_Click(object sender, EventArgs e)

You could expose a Search Event from your UpdateForm and subscribe to this event in the SystemForm

namespace SalesSystem
{
    public partial class SystemForm : Form
    {
        public SystemForm()
        {
            InitializeComponent();
        }    

        protected void searchButton_Click(object sender, EventArgs e)
        {
           //search code
        }

        private void updateButton_Click(object sender, EventArgs e)
        {
            try
            {
                UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text,            dbdirec, dbfname);

                upForm.OnSearch += Search;                      

                upForm.ShowDialog(this);
            }
            catch (Exception)
            {
                //
            }
        }

        private void Search(string searchParameter)
        {
            ....
        }

    }


namespace SalesSystem
{
    public delegate void SearchEventHandler(string searchParameter); 

    public partial class UpdateForm : Form
    {

        public event SearchEventHandler OnSearch;

        public UpdateForm(string selectedPerson, string dbdirec, string dbfname)
        {
            InitializeComponent();

        }

        private void updateButton_Click(object sender, EventArgs e)
        {
            //do stuff

            OnSearch("SearchThis");

            this.Close();
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top