在用户控件单击事件中切换主窗体中的用户控件
switch usercontrols in mainform within a usercontrol click event
这听起来可能很愚蠢,但我很难弄明白;任何帮助将不胜感激:
我有两个用户控件,名为“Safety_Check”和“ OEE_Track”。在我的 MainForm 中,我有一个名为“pnl_main_controller[ 的面板=47=]” 这是我显示我的两个用户控件的地方。我的主窗体上有两个按钮,我可以在两者之间动态切换,没有任何问题。
Safety_Check 用户控制;
public partial class Safety_Check : UserControl
{
private static Safety_Check _instance;
public static Safety_Check instance
{
get
{
if (_instance == null)
_instance = new Safety_Check();
return _instance;
}
}
public Safety_Check()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
///////------------------------
}
}
OEE_Track 用户控制
public partial class OEE_Track : UserControl
{
private static OEE_Track _instance;
public static OEE_Track instance
{
get
{
if (_instance == null)
_instance = new OEE_Track();
return _instance;
}
}
public OEE_Track()
{
InitializeComponent();
}
}
主窗体:
public partial class MainForm : Form
{
private void btn_reg_Click(object sender, EventArgs e)
{
if (!pnl_main_controller.Contains(Safety_Check.instance))
{
pnl_main_controller.Controls.Add(Safety_Check.instance);
Safety_Check.instance.Dock = DockStyle.Fill;
Safety_Check.instance.BringToFront();
}
else
{
Safety_Check.instance.BringToFront();
} }
private void btn_OEE_Click(object sender, EventArgs e)
{
if (!pnl_main_controller.Contains(OEE_Track.instance))
{
pnl_main_controller.Controls.Add(OEE_Track.instance);
OEE_Track.instance.Dock = DockStyle.Fill;
OEE_Track.instance.BringToFront();
}
else
{
OEE_Track.instance.BringToFront();
}
}
我想做的是在我的“Safety_Check”用户控件,每当我按下这个,我想要“Safety_Check”在“pnl_main_controller”上消失并带来“OEE_Track”到面板
控件之间的交互有多种解决方案。控件是 classes 并且与任何其他 class 一样,它们可以使用它们的 public 属性和方法或使用一些中介相互交互。
在这种情况下,您的控件不需要相互了解,也不需要直接相互交互:
- 他们可以要求另一个知道这两个控件的对象为他们完成这项工作。
- 或者他们可以提出他们的请求通知,订阅该通知的人将提供该通知。
要让另一个对象为他们完成工作,您有多种解决方案。例如,您可以在父窗体和子控件中实现特定接口,将父控件转换为该特定接口并调用为您完成工作的特定方法。
为了提高请求通知,一个简单的解决方案是依赖事件。您可以在子控件中创建一个事件,并在需要父控件为您做某事时引发它。然后在父级订阅该事件并完成工作。
示例 - 使用事件
我假设你有 UserControl1
里面有 Button1
并且你已经处理了 Button1
的 Click
事件。然后你可以创建 Button1Clicked
事件并在 Button1
单击时引发它:
public event EventHandler Button1Clicked;
private void Button1_Click(object sender, EventArgs e)
{
Button1Clicked?.Invoke(this, e);
}
然后在父表单中,订阅事件并做任何你想做的事情:
private void userControl11_Button1Clicked(object sender, EventArgs e)
{
//Hide userControl11 and show userControl21
}
示例 - 使用界面
我假设,您有一个包含一些标准方法的接口:
public interface IDoSomething
{
void DoSomething();
void DoSomethingElse();
}
并且您已经在父表单中实现了接口:
public class Form1: Form, IDoSomething
{
// ...
public void DoSomething()
{
//Hide userControl11 and show userControl21
}
public void DoSomethingElse()
{
// ...
}
}
然后在你的用户控件中:
private void Button1_Click(object sender, EventArgs e)
{
var f = FindForm() as IDoSomething;
if(f!=null)
f.DoSomething();
}
我想稍微扩展一下 Reza Aghaei 的回答。我认为它可以变得比现在更好。
第一种方法
如果我是你,我会有一些接口 ICheckedView
至少有 1 个方法可以像这样实现:
ICheckedView
{
void Continue();
}
现在,我们可以将此接口应用到我们解决方案中的任何 class,不过最有可能是视图。接下来,我将使您的主窗体实现此接口并实现所需的方法。在 this 案例中,我们希望我们的主窗体从面板中删除控件并添加一个新控件。坦率地说,我们的安全检查控件不需要(也许不应该)了解其他控件或接下来会发生什么。它只是用于控制流。
最后,你需要添加一个public 属性,或者甚至是构造函数的参数 for Safety_Check 其中包含一个 ICheckedView
。当您的安全检查控件被点击时,它可以告诉进入其中的任何人(我们称之为客户)它必须继续。
第二种方法
可以用 action delegate 来完成。
如果您将 Action
委托添加到您的安全检查中,您可以只弹出其签名与该委托匹配的任何方法 (void methodName()
)。 Safety_Check 控件的构造函数应包含一个 Action,并且该 Action 将分配给 class 的私有字段。然后在调用的时候,直接调用那个action就可以了。
此方法的注意事项
因为我们可能首先从 UI 线程调用,所以我们可能没问题,但您需要在这里考虑线程安全。 invoke required 模式可以帮助您解决这个问题。
这听起来可能很愚蠢,但我很难弄明白;任何帮助将不胜感激:
我有两个用户控件,名为“Safety_Check”和“ OEE_Track”。在我的 MainForm 中,我有一个名为“pnl_main_controller[ 的面板=47=]” 这是我显示我的两个用户控件的地方。我的主窗体上有两个按钮,我可以在两者之间动态切换,没有任何问题。
Safety_Check 用户控制;
public partial class Safety_Check : UserControl
{
private static Safety_Check _instance;
public static Safety_Check instance
{
get
{
if (_instance == null)
_instance = new Safety_Check();
return _instance;
}
}
public Safety_Check()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
///////------------------------
}
}
OEE_Track 用户控制
public partial class OEE_Track : UserControl
{
private static OEE_Track _instance;
public static OEE_Track instance
{
get
{
if (_instance == null)
_instance = new OEE_Track();
return _instance;
}
}
public OEE_Track()
{
InitializeComponent();
}
}
主窗体:
public partial class MainForm : Form
{
private void btn_reg_Click(object sender, EventArgs e)
{
if (!pnl_main_controller.Contains(Safety_Check.instance))
{
pnl_main_controller.Controls.Add(Safety_Check.instance);
Safety_Check.instance.Dock = DockStyle.Fill;
Safety_Check.instance.BringToFront();
}
else
{
Safety_Check.instance.BringToFront();
} }
private void btn_OEE_Click(object sender, EventArgs e)
{
if (!pnl_main_controller.Contains(OEE_Track.instance))
{
pnl_main_controller.Controls.Add(OEE_Track.instance);
OEE_Track.instance.Dock = DockStyle.Fill;
OEE_Track.instance.BringToFront();
}
else
{
OEE_Track.instance.BringToFront();
}
}
我想做的是在我的“Safety_Check”用户控件,每当我按下这个,我想要“Safety_Check”在“pnl_main_controller”上消失并带来“OEE_Track”到面板
控件之间的交互有多种解决方案。控件是 classes 并且与任何其他 class 一样,它们可以使用它们的 public 属性和方法或使用一些中介相互交互。
在这种情况下,您的控件不需要相互了解,也不需要直接相互交互:
- 他们可以要求另一个知道这两个控件的对象为他们完成这项工作。
- 或者他们可以提出他们的请求通知,订阅该通知的人将提供该通知。
要让另一个对象为他们完成工作,您有多种解决方案。例如,您可以在父窗体和子控件中实现特定接口,将父控件转换为该特定接口并调用为您完成工作的特定方法。
为了提高请求通知,一个简单的解决方案是依赖事件。您可以在子控件中创建一个事件,并在需要父控件为您做某事时引发它。然后在父级订阅该事件并完成工作。
示例 - 使用事件
我假设你有 UserControl1
里面有 Button1
并且你已经处理了 Button1
的 Click
事件。然后你可以创建 Button1Clicked
事件并在 Button1
单击时引发它:
public event EventHandler Button1Clicked;
private void Button1_Click(object sender, EventArgs e)
{
Button1Clicked?.Invoke(this, e);
}
然后在父表单中,订阅事件并做任何你想做的事情:
private void userControl11_Button1Clicked(object sender, EventArgs e)
{
//Hide userControl11 and show userControl21
}
示例 - 使用界面
我假设,您有一个包含一些标准方法的接口:
public interface IDoSomething
{
void DoSomething();
void DoSomethingElse();
}
并且您已经在父表单中实现了接口:
public class Form1: Form, IDoSomething
{
// ...
public void DoSomething()
{
//Hide userControl11 and show userControl21
}
public void DoSomethingElse()
{
// ...
}
}
然后在你的用户控件中:
private void Button1_Click(object sender, EventArgs e)
{
var f = FindForm() as IDoSomething;
if(f!=null)
f.DoSomething();
}
我想稍微扩展一下 Reza Aghaei 的回答。我认为它可以变得比现在更好。
第一种方法
如果我是你,我会有一些接口 ICheckedView
至少有 1 个方法可以像这样实现:
ICheckedView
{
void Continue();
}
现在,我们可以将此接口应用到我们解决方案中的任何 class,不过最有可能是视图。接下来,我将使您的主窗体实现此接口并实现所需的方法。在 this 案例中,我们希望我们的主窗体从面板中删除控件并添加一个新控件。坦率地说,我们的安全检查控件不需要(也许不应该)了解其他控件或接下来会发生什么。它只是用于控制流。
最后,你需要添加一个public 属性,或者甚至是构造函数的参数 for Safety_Check 其中包含一个 ICheckedView
。当您的安全检查控件被点击时,它可以告诉进入其中的任何人(我们称之为客户)它必须继续。
第二种方法
可以用 action delegate 来完成。
如果您将 Action
委托添加到您的安全检查中,您可以只弹出其签名与该委托匹配的任何方法 (void methodName()
)。 Safety_Check 控件的构造函数应包含一个 Action,并且该 Action 将分配给 class 的私有字段。然后在调用的时候,直接调用那个action就可以了。
此方法的注意事项
因为我们可能首先从 UI 线程调用,所以我们可能没问题,但您需要在这里考虑线程安全。 invoke required 模式可以帮助您解决这个问题。