我有一个程序,它有一个父表单,然后创建一个子表单。单击子窗体中的updateButton后,我希望触发父窗体中的searchButton。
但是出于保护原因我收到错误。我试过将所有东西设置为公开只是为了看,仍然不适合我。
错误1'SalesSystem.SystemForm.searchButton'由于无法访问 其保护级别SalesSystem \ UpdateForm.cs 111 20 SalesSystem
这是我到目前为止所做的。
父代码
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)
{
//
}
}
}
儿童代码
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();
}
}
}
答案 0 :(得分:2)
默认情况下,您的searchButton
按钮控件在WinForm中设置为private
。您已经说过要将所有内容都设置为公开,但我认为您的意思是您已将所有内容都设置为公开发布的代码。有几种方法可以解决这个问题。直接修复只需转到Visual Studio设计器,选择按钮,并将其Modifier
属性设置为internal
或public
。
但是,您似乎正在关闭您的表单,所以我只是让我的父表单订阅表单的FormClosing
事件。
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);
如果您没有关闭表单,那么您可以创建自己的父表单订阅的事件处理程序。
答案 1 :(得分:1)
您有两个选择:
在父表单中创建public void search()
方法。然后,您不是直接访问父窗体上的按钮并调用其单击事件,而是直接运行搜索代码。新方法不依赖于GUI元素,从不同的形式访问它是没有问题的。
更好的解决方案是创建委托。委托是将在运行时分配的执行目标。父表单仍然具有public void search()
方法。当它创建子表单时,它会将该函数的名称作为参数传递。子表单不知道父表单(而不是第一个选项,其中子必须知道有一个名为search()
的方法)。当需要通知创建子表单的人时,将调用该委托。这是一个小例子:
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)
{
//
}
}
}
孩子形成:
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();
}
}
答案 2 :(得分:0)
您应该使用"Model View Controller"或"Model View Presenter"模式来处理此类问题。
每个表单只应关注向用户显示其内容。在响应UI事件(如按钮点击)时,每个表单(即每个"View"
)应该只是引发一个事件,通知控制器/演示者发生了某些事情。
然后,控制器/演示者应该做出适当的响应。然后将不同形式(例如示例中的父表单和子表单)连接在一起的逻辑封装在Controller类中。这种逻辑并不属于任何一种形式。
我写了一个例子,演示了一个简单的设计,在不久前的另一个答案中做这种事情。而不是在这里复制/粘贴它,我只是给你一个链接:
How to make Form1 label.text change when checkbox on form2 is checked?
你必须向下滚动才能看到我的答案。它与你正在做的大致相似;希望它对你有意义!按照说明制作测试应用程序并运行它以查看会发生什么。
答案 3 :(得分:0)
我很累,可能会遗漏一些东西,但这是正确的行为。
您的子表单不会直接从您的父表单继承。
您的父窗体具有受保护的级别,因此只有它和扩展它的类才能访问该方法。
2个解决方案:
public partial class UpdateForm:SystemForm
public void searchButton_Click(object sender,EventArgs e)
答案 4 :(得分:0)
您可以从UpdateForm公开搜索事件,并在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();
}
}
}