Windows Form中如何将Second.GetInfo()的字符串传递至主窗体Favorit?
解决方案:将Second类的字符串传递到主窗体Favorit
你的思路完全正确——用get/set属性暴露TextBox内容是合适的,但目前代码里Second类的静态方法没办法访问到主窗体的现有实例,所以没法直接设置属性。下面给你两种可行的实现方式,你可以根据需求选择:
方法1:直接传递主窗体实例(简单直接)
这种方式最容易上手,核心是把当前的Favorit窗体实例传给Second类的方法,这样就能直接操作它的属性:
步骤1:修改Second类的方法
首先让GetInfo返回获取到的字符串,然后在StartBrowser里接受主窗体实例(通过你定义的IForm接口):
public class Second : Form { private static ChromeDriver driver = null; public static ChromeDriver GetDriver() { if (driver == null) { driver = new ChromeDriver(); } return driver; } // 新增IForm参数,接收主窗体实例 public static void StartBrowser(ChromeDriver driver, string IDevent, IForm mainForm) { driver.Navigate().GoToUrl("myURL" + IDevent); // 获取信息后直接设置主窗体的属性 string commandName = GetInfo(); mainForm.CommandName1 = commandName; } // 修改为返回字符串 public static string GetInfo() { System.Threading.Thread.Sleep(2000); string CommandName1 = driver.FindElement(By.XPath(".//*[@id='react-root']/div/div[2]/div/div[1]/div/div[1]/div/div[1]/div/header/div[2]/span[1]")).Text; string CommandName2 = driver.FindElement(By.XPath(".//*[@id='react-root']/div/div[2]/div/div[1]/div/div[1]/div/div[1]/div/header/div[2]/span[2]")).GetAttribute("innerHTML"); return CommandName1; } }
步骤2:在主窗体中传递自身实例
在bStart_Click方法里,把this(当前Favorit实例)传给StartBrowser:
private void bStart_Click(object sender, EventArgs e) { string ID = tbGetID.Text; // 传递当前窗体实例 Second.StartBrowser(Second.GetDriver(), ID, this); }
方法2:使用事件(低耦合,更优雅)
如果不想让Second类直接依赖主窗体,用事件的方式更符合面向对象设计,而且能处理多线程问题(因为ChromeDriver的操作是在非UI线程,直接修改UI会报错):
步骤1:在Second类中定义事件
public class Second : Form { private static ChromeDriver driver = null; // 定义事件,传递获取到的两个字符串 public static event Action<string, string> InfoReceived; public static ChromeDriver GetDriver() { if (driver == null) { driver = new ChromeDriver(); } return driver; } public static void StartBrowser(ChromeDriver driver, string IDevent) { driver.Navigate().GoToUrl("myURL" + IDevent); GetInfo(); } public static void GetInfo() { System.Threading.Thread.Sleep(2000); string CommandName1 = driver.FindElement(By.XPath(".//*[@id='react-root']/div/div[2]/div/div[1]/div/div[1]/div/div[1]/div/header/div[2]/span[1]")).Text; string CommandName2 = driver.FindElement(By.XPath(".//*[@id='react-root']/div/div[2]/div/div[1]/div/div[1]/div/div[1]/div/header/div[2]/span[2]")).GetAttribute("innerHTML"); // 触发事件,传递数据 InfoReceived?.Invoke(CommandName1, CommandName2); } }
步骤2:在主窗体中订阅事件
在主窗体的构造函数里订阅事件,并且注意切换到UI线程修改控件:
public partial class Favorit : Form, IForm { public Favorit() { InitializeComponent(); // 订阅Second类的事件 Second.InfoReceived += Second_InfoReceived; } private void Second_InfoReceived(string commandName1, string commandName2) { // 因为ChromeDriver在非UI线程,必须用Invoke切换到UI线程才能修改控件 if (tbCommandName1.InvokeRequired) { tbCommandName1.Invoke(new Action(() => { tbCommandName1.Text = commandName1; // 如果有第二个TextBox,也可以一起设置 // tbCommandName2.Text = commandName2; })); } else { tbCommandName1.Text = commandName1; } } // 你的其他代码不变 public string CommandName1 { get { return tbCommandName1.Text; } set { tbCommandName1.Text = value; } } private void bStart_Click(object sender, EventArgs e) { string ID = tbGetID.Text; Second.StartBrowser(Second.GetDriver(), ID); } }
注意事项
- 方法2里的
Invoke是必须的:因为ChromeDriver的操作是在后台线程,直接在后台线程修改UI控件会抛出跨线程异常,所以必须通过Invoke把操作切换到UI线程执行。 - 如果需要传递多个数据(比如你获取的CommandName1和CommandName2),方法1可以扩展IForm接口添加更多属性,方法2的事件可以传递自定义类或者元组。
内容的提问来源于stack exchange,提问作者The Vee
相关产品推荐
相关产品推荐

