我在另一个名称空间中从另一个类更改文本时遇到问题。我有第一个Form1
课程:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
static Form1 mainForm;
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AllocConsole();
public static String LinkToApi = "http://google.com/api/";
public static Comunicator comunicator;
public static int debug = 5;
public Form1()
{
InitializeComponent();
AllocConsole(); // allow console
if(Form1.debug >= 3) Console.WriteLine("Application started");
comunicator = new Comunicator();
mainForm = this;
}
private void TestButton_Click(object sender, EventArgs e)
{
TestButton.Text = "Loading";
comunicator.TestConnection();
}
}
}
和此Comunicator
类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Collections.Specialized;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using System.Threading;
namespace WindowsFormsApplication1
{
public class Comunicator
{
private String action = "idle";
public static Thread Start(Action action)
{
Thread thread = new Thread(() => { action(); });
thread.Start();
return thread;
}
public Comunicator()
{
}
public void TestConnection()
{
if (Form1.debug >= 3) Console.WriteLine("Testing connection");
// thread test
Start(new Action(ApiTest));
}
public void ApiTest()
{
if (Form1.debug >= 3) Console.WriteLine("API test begin");
// Create a request for the URL.
WebRequest request = WebRequest.Create("http://www.bogotobogo.com/index.php");
// If required by the server, set the credentials.
request.Credentials = CredentialCache.DefaultCredentials;
// Get the response.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Display the status.
Console.WriteLine(response.StatusDescription);
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Cleanup the streams and the response.
reader.Close();
dataStream.Close();
response.Close();
// Console.Read();
if (Form1.debug >= 3) Console.WriteLine("API test end");
// Form1.StaticTestButton.Text = "Loaded"; <---- CHANGE HERE
}
}
}
甚至不是表格类(我想保持一切都很好和干净)。我想将TestButton
文本更改为“已加载”,但在尝试执行此操作时出现错误,就像Form1.TestButton
类中不存在Comunicator
一样。
我试图实例化这个类,我做了几个变量静态...没有,仍然出错。
有什么问题?我怎么解决这个问题?
请求必须是异步的,这就是我使用线程的原因。
答案 0 :(得分:1)
您应该分开关注点,并且您不应该在课堂上与UI进行通信,这与UI无关。 你应该重写你的代码。 但作为快速解决方案,您应该执行以下操作。
在课程Comunicator
中,您可以执行此类字段。
private readonly Action<string> _notifySimpleMessageAction;
然后添加到Communicator
构造函数参数notifyFunction
。构造函数中的代码:
_notifySimpleMessageAction = notifyFunction
之后,您应该按照以下方式创建Communicator:
communicator = new Communicator((notification)=>
{
StaticTestButton.BeginInvoke((MethodInvoker)(() => StaticTestButton.AppendText(notification)));
});
然后在你的方法结束时你应该
_notifySimpleMessageAction("Loaded")
答案 1 :(得分:0)
控制器类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ControllerDemonstrator
{
public class Controller
{
public event EventHandler CommunicatorDataLoaded;
public event EventHandler FormTestConnection;
private Form1 _form;
private Communicator _communicator;
public Form1 MainForm
{
get { return _form; }
}
public Controller()
{
_form = new Form1(this);
_form.TestConnection += _form_TestConnection;
_form.FormClosed += _form_FormClosed;
_communicator = new Communicator(this);
_communicator.DataLoaded += _communicator_DataLoaded;
}
public void Start()
{
_form.Show();
}
void _form_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
{
// put any code to clean up the communicator resources (if needed) here
// --------------------------------------------------------------------
_communicator = null;
// Then exit
// ---------
Application.Exit();
}
private void _communicator_DataLoaded(object sender, EventArgs e)
{
if (null != CommunicatorDataLoaded)
{
CommunicatorDataLoaded(sender, e);
}
}
private void _form_TestConnection(object sender, EventArgs e)
{
if (null != FormTestConnection)
{
FormTestConnection(sender, e);
}
}
}
}
带一个按钮的基本表单(_testButton):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ControllerDemonstrator
{
public partial class Form1 : Form
{
public event EventHandler TestConnection;
public Form1(Controller controller)
{
InitializeComponent();
controller.CommunicatorDataLoaded += controller_CommunicatorDataLoaded;
}
void controller_CommunicatorDataLoaded(object sender, EventArgs e)
{
_testButton.Text = "Loaded";
}
private void _testButton_Click(object sender, EventArgs e)
{
if (null != TestConnection)
{
TestConnection(this, new EventArgs());
}
}
}
}
Communicator类(所有内容都已被删除,您需要添加逻辑):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ControllerDemonstrator
{
public class Communicator
{
public event EventHandler DataLoaded;
public Communicator(Controller controller)
{
controller.FormTestConnection += controller_FormTestConnection;
}
private void controller_FormTestConnection(object sender, EventArgs e)
{
// put your code that does the connection here
// -------------------------------------------
if (null != DataLoaded)
{
DataLoaded(this, new EventArgs());
}
}
}
}
在你的Program.cs中(假设你是如何开始申请的):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ControllerDemonstrator
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Controller c = new Controller();
Application.Run(c.MainForm);
}
}
}
通过这种设计,传播者不知道形式和反面。您可以将其扩展为具有不同类型的通信器/表单/等,并让控制器跟踪所有内容。测试这样的代码也要容易得多,因为你可以自己测试每个单独的部分,因为它们不相互依赖。这是一个快速而肮脏的实现。做一些关于模型视图控制器设计模式的研究(不是用于asp.Net的Microsoft MVC,而是实际的设计模式)。使用MVC设计模式对应用程序进行代码编写需要更多的代码,但它使测试更容易,更易于维护。