C# 从窗体访问类,反之亦然
在网上搜寻了两天,但没有找到一个我能正确理解的解决方案后,我不得不在这里问一个答案 我有一个用vb.net编写的windows窗体应用程序,运行良好。我决定用c语言重写这篇文章,我认为这不会有太大问题,但是 我在项目中有两门课: FormJobs和AppJobs FormJobs包含以某种方式修改表单的方法和函数 AppJobs包含用于其他一切(检查、扫描等)的方法和函数 在我的主窗体(FrmStart)上,On_load事件使用AppJobs中的函数检查网络是否正常(public bool CheckNetConnection),然后检查以确保根保存文件夹存在(public void CheckRoot) 如果CheckNetConnection为false或CheckRoot不存在,则FormJobs类中的方法会将一些按钮设置为禁用,将一些标签设置为显示错误信息,并设置窗体的高度 上面的代码在VB.net中运行,但我一直在使用C#代码获取StackOverflowException或NullReferenceException 我知道出现异常的原因是因为这两个类和表单都在互相调用,所以我知道我需要删除这段代码,但我不确定如何让每个类和表单互相访问。这显然是一个糟糕的设计,因为我才刚刚开始学习C#,所以在此方面的任何帮助都将不胜感激 但我的主要问题是:-如何获得访问多个类的表单? 允许类相互访问吗? 让类对表单进行更改 FrmStart代码C# 从窗体访问类,反之亦然,c#,winforms,visual-studio,C#,Winforms,Visual Studio,在网上搜寻了两天,但没有找到一个我能正确理解的解决方案后,我不得不在这里问一个答案 我有一个用vb.net编写的windows窗体应用程序,运行良好。我决定用c语言重写这篇文章,我认为这不会有太大问题,但是 我在项目中有两门课: FormJobs和AppJobs FormJobs包含以某种方式修改表单的方法和函数 AppJobs包含用于其他一切(检查、扫描等)的方法和函数 在我的主窗体(FrmStart)上,On_load事件使用AppJobs中的函数检查网络是否正常(public bool C
AppJobs Appjobs = new AppJobs();
private void FrmStart_Load(object sender, EventArgs e)
{
KeyPreview = true;
if (Appjobs.CheckNetConnection(this) == true)
{
Appjobs.CheckRoot(this);
}
AppJobs代码
public class AppJobs
{
FormJobs Formjobs = new FormJobs();
public string AppRoot = Properties.Settings.Default.DefaultFolder;
public string DefaultDevice = Properties.Settings.Default.DefaultScanner;
public bool NoDirectory = false;
DialogResult MsgBoxQuestion;
public bool CheckNetConnection(Form StartForm)
{
IPHostEntry ServerIP = new IPHostEntry();
bool ConnectedToServer = false;
string CurrentRoot = "MyServer";
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
try
{
IPHostEntry DNSTest = Dns.GetHostEntry(CurrentRoot);
if (DNSTest.AddressList.Length > 0)
{
ConnectedToServer = true;
}
else
{
ConnectedToServer = false;
}
}
catch (System.Net.Sockets.SocketException ex)
{
ConnectedToServer = false;
}
}
return ConnectedToServer;
}
public void CheckRoot(Form StartForm)
{
if (string.IsNullOrEmpty(AppRoot))
{
Formjobs.SetHeight(StartForm);
return;
}else if(AppRoot == "0")
{
Formjobs.SetHeight(StartForm);
return;
}
else
{
if ((!Directory.Exists(AppRoot)))
{
NoDirectory = true;
MsgBoxQuestion = MessageBox.Show(AppRoot + " is set, but the directory does not exist." + Environment.NewLine
+ Environment.NewLine + "Would you like to create the folder now?", "Root folder missing", MessageBoxButtons.YesNo);
if (MsgBoxQuestion == DialogResult.Yes)
{
Directory.CreateDirectory(AppRoot);
NoDirectory = false;
}
else
{
MessageBox.Show("You will not be able to use this program until you create a root folder.", "No root folder selected",MessageBoxButtons.OK);
}
}
}
}
}
格式作业代码
public class FormJobs
{
AppJobs Appjobs = new AppJobs();
public void SetHeight(Form StartForm)
{
if (Appjobs.AppRoot == null | Appjobs.AppRoot == "0") {
if (Appjobs.DefaultDevice == null | Appjobs.DefaultDevice == "0") {
if (StartForm.Controls["MenuStrip1"].Visible == true) {
StartForm.Height = 167;
StartForm.Controls["LblNoRoot"].Visible = true;
StartForm.Controls["LblNoRoot"].Location = new Point(0, 24);
StartForm.Controls["LblNoRoot"].Text = "There is no root folder selected. Please select a root folder to continue.";
StartForm.Controls["LblNoDevice"].Visible = true;
StartForm.Controls["LblNoDevice"].Location = new Point(0, 48);
StartForm.Controls["LblNoDevice"].Text = "There is no default device selected. Please select a default device to continue.";
StartForm.Controls["BtnOkTickets"].Enabled = false;
StartForm.Controls["BtnQueryTickets"].Enabled = false;
StartForm.Controls["BtnSearch"].Enabled = false;
}else
{
StartForm.Height = 147;
StartForm.Controls["LblNoRoot"].Visible = true;
StartForm.Controls["LblNoRoot"].Location = new Point(0, 9);
StartForm.Controls["LblNoRoot"].Text = "There is no root folder selected. Please select a root folder to continue.";
StartForm.Controls["LblNoDevice"].Visible = true;
StartForm.Controls["LblNoDevice"].Location = new Point(0, 33);
StartForm.Controls["LblNoDevice"].Text = "There is no default device selected. Please select a default device to continue.";
StartForm.Controls["BtnOkTickets"].Enabled = false;
StartForm.Controls["BtnQueryTickets"].Enabled = false;
StartForm.Controls["BtnSearch"].Enabled = false;
}
}
扩展注释:只需删除FormJobs和AppJobs类中的
new
部分。
将代码保留在FormJobs类中,如:AppJobs Appbj代码>
然后在主窗体中,在某个点创建FormJobs对象和AppJobs对象,并设置其属性。
即主要形式:
AppJobs appObj = new AppJobs();
FormJobs formObj = new FormJobs();
formObj.appObj = appObj;
虽然我必须说我不喜欢你在这方面采取的方法
您应该考虑另一种方法,或者至少重构您的代码,使FormJobs不需要AppJobs方法,反之亦然,所有对FormJobs和AppJobs的调用都来自主窗体。问题的原因之一是每个人都在更改您的StartForm
。除此之外,如果Startform
发生了变化,那么这条意大利面条就很难理解,当然也无助于使类可重用和可维护
在我看来,AppJobs
旨在决定表单的外观(例如,它决定StartForm
应更改高度),而FormJobs
执行更改此高度所需的计算StartForm
显然只是允许每个人对他进行更改
更好的设计是StartForm
不会要求AppJobs
更改其大小,并询问操作员是否应生成文件夹。相反,如果你应该询问appJobs的建议:“你认为我应该有多高?”。之后,它可以问FormJobs:“请根据此规格调整我的身高”
FormJobs
应该相信StartForm
已经收集了有关StartForm
应该是什么样子的正确信息FormJobs
不应询问AppJobs
任何信息:“嘿,AppJobs,StartForm要求我将其外观更改为某些规格,但我不确定StartForm是否正确完成了其工作。请告诉我这些规格是否正确,并提供一些缺少的信息”)
正确的任务划分是:
- AppJobs根据其内部状态(a.o.Approt和某些文件夹的存在)指定任何
StartForm
的格式
StartForm
显示所有项目。他决定向谁索取规格,以及如何处理返回的规格。他也是唯一一个与运营商沟通的人
FormJobs
是一个显然从StartForm
中知道所有元素的类。如果只有一种类型的StartForm
,那么Appjobs
应该是StartForm
类的一部分。如果您认为可能有几个不同的Startform
类,它们都具有相同的元素,应该进行类似的操作,那么这些Startform
类难道不应该从FormJobs
类派生出来吗
无论如何,重新设计时不要让每个人都操纵StartForm
显然,根据Approt、defaultDevice等的不同,StartForm的布局数量有限。在if之后,您似乎缺少了一些“其他”,因此此列表可能不准确。但你还是会有这样的想法:
enum StartFormLayouts
{
DefaultDevice0,
AppRoot0,
Other,
}
// class that specifies the layout of any startform
class AppJobs
{
private bool IsAppRoot0
{
get{return Appjobs.AppRoot == null || Appjobs.AppRoot == "0";}
}
private bool IsDefaultDevice0
{
get{return Appjobs.DefaultDevice == null || Appjobs.DefaultDevice == "0";}
}
public StartFormLayoug GetPreferredLayout()
{
if (this.IsAppRoot0)
{
if (this.IsDefaultDevice)
{
return StartFormLayout.DefaultDevice0;
}
else
return StartFormLayout.AppRoot0;
}
else
{
return StartFormLayout.Other;
}
}
public bool ShouldAskDirectoryCreation()
{
return (!this.IsAppRoot0 && !Directory.Exists(AppRoot));
}
}
请注意,此类不需要StartForm,也不需要AppJobs。它可以与任何想要知道是否应该请求DirectoryCreation的类一起工作。因为它也不会说任何语言,所以即使是中文StartForm
也可以使用它。毕竟,StartForm
是唯一一个知道它说什么语言以及在请求某个布局时该做什么的人
此外,您是否注意到我使用了双精度|
来使用布尔OR而不是按位OR
和我使用语句如<代码>(A)< /COD>而不是<代码>(如果(a=true)< /COD> C是布尔布尔,是与C和C++中的Booleans相矛盾的。< /P>
应该能够根据请求的布局进行布局的各种表单的类包含与
这取决于你是否决定让它成为bas
public Interface IStartForm
{
public int Height {get; set;}
public Label LabelNoRoot {get;}
public Label LabelNoDevice {get; }
public Button BtnTickets {get;}
...
public SetHeight(StartFormLayout layout, IStartForm startForm)
{
switch (layout)
{
case StartFormLayout.DefaultDevice0:
if (startForm.MenuStrip.Visible)
{
startForm.Height = ...;
startForm.LabelNoRoot.Location = ...
// etc
}
else
{
...
class StartForm : Form, IStartForm
{
public Label LabelNoRoot {get{return this.label1; } }
...
private void FrmStart_Load(object sender, EventArgs e)
{
AppJobs layoutdesigner = new AppJobs(...);
StartFormLayout layoutdesigner = layouter.GetPreferredLayout();
FormJobs layouter = new FormJobjs();
layouter.SetHeight(this)
}