使用一种forms的控制到另一种forms

我有一个应用程序,在一种forms( Form1 )我有很多checkBoxes和textBoxes,在Form2我只有一个textBox,但我想从Form1文本框中放入一些内容并放入Form2文本框,像这样,但在表单之间:

 textBox1.Text = "Test: " + textBox1 + "\n" + textBox3; 

作为Form2textBox1Form1的第二个textBox1textBox3 ,但我怎么能这样做? 谢谢。

根据您启动第二个表单的方式,您可以在Form2中分配一个引用Form1的成员对象,或者如果您使用的是MDI接口,则可以使用表单集合从中检索对Form1的引用。

例如,您可以在Form2类中使用以下代码:

 public partial class Form2 : Form { public Form1 LaunchOrigin { get; set; } // and so on 

现在,您可以在启动Form2时分配LaunchOrigin成员。 这是一个例子:

 Form2 newForm = new Form2(); newForm.LaunchOrigin = this; newForm.Show(); 

您现在可以访问Form1及其所有成员。 这是一个简单的例子:

  private void Form2_Load(object sender, EventArgs e) { this.Text = LaunchOrigin.Text; } 

您必须记住控件被声明为私有,因此您无法直接访问它们。 你可以在Form1上写一个引用该控件的属性,但这通常是个坏主意。 但是,为了完整起见,这里有一些代码可用于公开Form1上的按钮:

 public partial class Form1 : Form { public Button theButton; public Form1() { InitializeComponent(); theButton = button1; // where button1 is what I dragged on } // and so on 

虽然你所要求的相对容易实现,但它会让你走上一些脆弱的应用程序结构。 仔细想想你试图在表单之间展示什么,也许它应该是一个可以绑定到两个表单的独特类型,这样一旦你改变了底层类型,就可以改变两者的表示。

有很好的方法可以做到这一点和丑陋的方式…从UGLY开始:

  1. 最丑陋的一种方法是将对Form1的引用传递给Form2的构造函数,然后将该引用存储为字段以供日后使用。 它很讨厌,因为它在两者之间产生了非常紧密的耦合。 更改Form1的界面或行为会影响Form2。

  2. 一个不那么难看但仍然是hackish的方法是将Form1中的字符串值传递给Form2的构造函数 – 或者Form2上的一些公共/内部方法。 你仍然依赖于这些字符串,但至少它不是Form1和Form2的完全耦合。 只是期望Form2总是有一个Form1来为它们提供这些字符串。

…在这里填写一些更讨厌的变化。

我建议你研究一个解决这个问题的应用程序范围的解决方案,而不是创建inter-objec依赖项。

创建一个适用于轻量级“pub / sub” – 或发布/订阅 – 模型的消息传递接口。 我们的想法是,您的应用中有一些组件可以发布消息(您的字符串值 – 或更复杂的东西)以及您的应用中订阅消息的其他组件。

当Form 1启动时,它会在消息传递界面注册“嘿,我要发布这种类型的消息”(类型是你提供的一些指示)。 当表单2启动时,它会向消息传递接口注册“哟,当有人发布此类消息时,将其传递给我”。

发布者和订阅者都实现了一些已知的接口,以便您的消息处理程序可以与它们通信(IPublisher,ISubscriber) – 并接收/发送消息。 如果有必要,一个组件无论是发布者还是订阅者都没有理由(基本上将系统中的对象视为“同伴”或“同事”)一些MessageReceived事件和一些用于管理发布者/订阅者集合的代码好好去。

有关更多详细信息, 请查看Mediator模式 ,该模式更详细地描述了此类解决方案。

我认为大卫在达科他的答案和上面的杰夫唐尼奇给出了你所需要的一切,但我会“充实”杰夫明智地提出的更广泛方法的一个简单例子,我希望能让你开始。

我可能与杰夫的回答有一点分歧,我相信这个问题的任何解决方案都是“dependency injection”或“依赖管理”的变体:即使你走“最抽象”的路线并拥有“出版商” “广播”事件给“未知用户”,但这只是我个人的看法。

这是一个简单的类型示例,有助于我在过去理解。

创建一个公共静态类,在其中插入要对可能修改的所有表单上的TextBox的静态引用(或存储表单本身或其他):定义公​​共静态方法以将数据从一个表单的文本框移动到另一个(s) ):一个非常快速的概述:(使用超长变量名称是故意的,仅用于说明目的)

 using System; using System.Collections.Generic; using System.Windows.Forms; // note : compiles against FrameWork 2.0 and 4.0 // wanted this to work w/o Linq, automatic properties, etc. namespace MessageHandler { public static class TextBoxMessenger { // internal List of TextBoxes of interest on all Forms internal static List _messageEnabledTBxes = new List(); // public Property to get/set the collection of TextBoxes of interest public static ListMessageEnabledTextBoxes { get { return _messageEnabledTBxes; } set { _messageEnabledTBxes = value; } } // in case you want to register one TextBox at a time public static void RegisterTextBoxForMessaging(TextBox theTBx) { _messageEnabledTBxes.Add(theTBx); } // send from one specific TBx to another public static void setText(TextBox originTBx, TextBox destinationTBx) { destinationTBx.Text = originTBx.Text; } // send to a specified list of TextBoxes public static void setText(TextBox originTBx, List destinationTBxs) { foreach (TextBox theTBx in destinationTBxs) { theTBx.Text = originTBx.Text; } } // set text in all other TextBoxes in MessageEnabledTextBoxes list public static void setText(TextBox originTBx) { foreach (TextBox theTBx in _messageEnabledTBxes) { // a needless check, since assigning the text of the // original TextBox to itself wouldn't "hurt" anything // but, imho, much better "practice" to always test if (theTBx != originTBx) theTBx.Text = originTBx.Text; } } } } 

所以在行动中这是如何工作的:让我们使用一个示例,其中您的Form1 Load事件如下所示:

 // assume Form2 has a single TextBox on it named 'textBox1' public Form2 myForm2; private void Form1_Load(object sender, EventArgs e) { myForm2 = new Form2(); myForm2.Show(); // register all the TextBoxes // note the redundant use of 'this here : it's a deliberate choice to make // the code communicate to a future user/reader/maintainter TextBoxMessenger.RegisterTextBoxForMessaging(this.textBox1); TextBoxMessenger.RegisterTextBoxForMessaging(this.textBox2); TextBoxMessenger.RegisterTextBoxForMessaging((TextBox)myForm2.Controls["textBox1"]); // or ... //TextBoxMessenger.MessageEnabledTextBoxes = new List //{ // this.textBox1, this.textBox2, (TextBox)myForm2.Controls["textBox1"] //}; } 

你可以通过在Form1上放一个按钮来测试上面这样:

 private void button1_Click(object sender, EventArgs e) { // tests // one to all ... //TextBoxMessenger.setText(this.textBox1); // one to a specific TextBox on another Form //TextBoxMessenger.setText(this.textBox1, (TextBox) myForm2.Controls["textBox1"]); // one to a List TextBoxMessenger.setText(this.textBox1, new List { this.textBox2, (TextBox)myForm2.Controls["textBox1"]}); } 

但是,请注意“丑陋”,“糟糕的代码气味”,例如:

(TextBox)myForm2.Controls [“textBox1”] //施法是邪恶的! 设置一个血腥的参考!

这是你想要摆脱的一种事情,超越这样的例子进入“竞技场”,杰夫,我相信,指向你。

希望这有用。 在“长期”中,消息传递到更高级别,我相信Jeff所规定的,是imho,使代码示例比这个例子更强大,更具“可推广性”的“皇家之路”。 最好,

在StackOverflow上多次询问此问题或其变体。 我认为这是由于对Forms和Visual Studio设计师的误解引起的。

  • 如何对转移对象之间-窗口forms,在-C
  • 如何对呼叫一个外形时,有-是-3-forms-IN-A-项目和数据传输之间
  • Windows的应用程序
  • 通过变量从-主型到输入表格
  • 如何对通值-从酮forms到另
  • 使用最控件-的酮forms-进入-另一个

Form只是一个恰好代表可视窗口的标准类。 将您自己的私有字段和公共属性添加到表单是完全合理的。

因此,当您需要在表单甚至应用程序的其他部分之间传递数据时,只需创建一个包含此数据的新类(而不是Form),并将其称为“ApplicationData”。 这完全取决于此类包含的属性和字段。

然后,对于需要访问数据的每个Form,添加ApplicationData类型的公共get / set属性。 最后在显示每个表单之前将此属性设置为ApplicationData对象。

然后,表单可以以任何需要的方式从中获取数据并更新此对象。 因为它是引用类型(即类),所以对象的所有更改对于使用相同对象的任何其他forms都是可见的。

这是一个粗略的例子。 请注意,此代码仅供参考:

 class ApplicationData{ private string _firstName; public string FirstName; { get { return _firstName;; } set { __firstName;=value; } } private string _lastName; public string LastName; { get { return _lastName; } set { __lastName=value; } } } class ChildForm : Form { private ApplicationData _applicationData=null; public ApplicationData AppData { get { return _applicationData; } set { _applicationData=value; } } void Load_Form(object sender, EventArgs args) { txtFirstName.Text=AppData.FirstName; txtLastName.Text=AppData.LastName; } void Form_Closing(object sender, EventArgs args) { AppData.FirstName=txtFirstName.Text; AppData.LastName=txtLastName.Text; } } class MainForm : Form { private ApplicationData _applicationData=new ApplicationData(); void Button_Click(object sender, EventArgs args) { ChildForm childForm=new ChildForm (); ChildForm.AppData=_applicatonData; ChildForm.ShowDialog(); string fullName=_applicatonData.LastName + " " + _applicatonData.FirstName } } 

其他问题(如发布者/订阅者设计)中的一些答案对于除了非常复杂的应用程序之外的任何事情都是完全过度的。 保持简单是一个非常重要的指导方针。

当然,Visual Studio设计器使得所有类必须在视觉上定向并从工具箱或“新建表单”选项创建,这无济于事。 这完全是错误的。

创建和使用“ApplicationData”类的设计模式是将演示文稿与内容分离的第一步。 很遗憾Visual Studio在这方面没有提供更多的指导。

您甚至可以通过编写参数化构造函数来完成它。

例如

 namespace SomeNamespace { public partial class Form2 : Form { string someStr = string.Empty; public Form2() { InitializeComponent(); } public Form2(string params) // Parametrized Constructor { InitializeComponent(); someStr = params } private void Form2_Load(object sender, EventArgs e) { Form2TextBox.Text = someStr ; } } } 

现在从Form1以这种方式调用Form2

 Form2 objF2 = new Form2(Form1TextBox1.Text); objF2.Showdialog();