如何与来自另一个类的 Form 控件通信? [英] How do I communicate with a control of a Form from another class?

查看:23
本文介绍了如何与来自另一个类的 Form 控件通信?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对 C# 有点新意,并接近我以外的东西.抱歉篇幅过长.

A little new to C#, and approaching something beyond me. Apologies for length.

我在 Visual Studio C# Express 中有一个 Windows 窗体应用程序,使用 VS 生成的默认类.我想从声明它的默认 Form1 以外的类启动和停止 Marquee 样式的 progressBar.这些看起来出奇的困难,我确定我遗漏了一些重要的东西.

I have a Windows Form application in Visual Studio C# Express, using the default classes VS spawns. I want to start and stop a Marquee style progressBar from a class other than the default Form1 in which it is declared. These seems surprisingly difficult, I am sure I am missing something important.

我的项目具有 Visual Studio 自动生成的常用类:Form1.cs、Form1.Designer.cs、Program.cs.我添加了 myClass.cs 想要谈论负载栏.我使用设计器将 progressBar1 栏添加到我的表单中,设置 Style:Marquee.

My project has the usual classes that Visual Studio auto generates: Form1.cs, Form1.Designer.cs , Program.cs . I added myClass.cs that wants to talk the load bar. I add progressBar1 bar to my form using the designer, setting Style:Marquee.

Form1.cs' Form() 构造函数中,我写

In Form1.cs' Form() constructor, I write

this.progressBar1.Visible = false;

这有效.智能感知看到"progresBar1.Form1.cs 中的代码可以查看和控制 Form1.Designer.cs 中声明的 progressBar1.这对我来说很有意义.

This works. Intellisense 'sees' progresBar1. code in Form1.cs can see and control progressBar1 declared in Form1.Designer.cs. this makes sense to me.

但是需要启动和停止加载条的函数必须存在于 myClass.cs 中.我希望能够在 myClass.cs 中像这样编码:

But the functions which need to start and stop the load bar must live in myClass.cs. I want to be able to code like this, within myClass.cs:

public void myFunction(){
    Form1.progressBar1.visible=true
    //do stuff that takes a bit of time
    Form1.progressBar1.visible=false
}

这不起作用.在 myClass.cs 中输入代码时,Intellisense 无法看到"progresBar1.实际上,intellisense 无法从 myClass.cs 中看到"Form1.cs 中的任何内容.添加到 Form1 的公共属性或函数不会对智能感知可见.这对我来说没有意义,我很困惑.这似乎是您想要经常轻松地做的事情.

This does not work. Intellisense cannot 'see' progresBar1 when typing code in myClass.cs. In fact, intellisense cannot 'see' anything in Form1.cs from within myClass.cs. No public propeties or functions added to Form1 ever become visible to intellisense. This does not make sense to me, I am confused. This seems like something you would want to do often and easily.

一些搜索表明,这种对表单控件的外部访问的阻止是有意为之.与将您的逻辑代码与 GUI 代码解耦"有关,这在原则上是有意义的.所以显然有一种预期的方法,但很难找到一个明确的例子.我只能找到完全在声明它们的表单中控制的负载条的示例,或者关于创建和注册事件或使用 Invoke 或其他我知之甚少的东西的简短示例.有许多明显的解决方案,但没有一个我能清楚地看到适用于我,或者我能够在我的无知中实施.

Some searching indicates that this blocking of external access to Form controls is by design. Something to do with 'decoupling' your logic code from GUI code, which makes sense in principal.So clearly there is an expected approach, yet an clear example is hard to find. I can only find examples of loadbars controlled from entirely within the Forms that declare them, or terse half-examples about creating and registering Events or using Invoke or other things I know too little about. There are many apparent solutions but none that I can see clearly apply to me, or that I am able to implement, in my ignorance.

如果我的表单是一个实例,我想我可以做到. 不.无论是否实例,Form1 控件永远不会暴露在 Form1.cs

I think I could do it if my Form were an instance. nope. instance or not, Form1 controls never become exposed outside of Form1.cs

那么,如何以正确的方式从声明它的默认 Form1 以外的类启动和停止 Marquee 样式的 progressBar?某处有明确且有用的例子吗?

So, How do I to start and stop a Marquee style progressBar from a class other than the default Form1 in which it is declared, in the proper way? Is there a clear and useful example somewhere?

推荐答案

您无法通过这种方式访问​​您的属性:

You can't access your properties this way:

Form1.progressBar1

因为 Form1 是一种类型(不是实例化的对象).您可以使用此方法访问的唯一方法或属性必须标记为 static.

because Form1 is a type (not an instantiated object). The only methods or properties you can access with this approach have to be marked as static.

要回答关于如何沟通的问题,您可能想使用您提到的事件方法.首先,您的逻辑类中需要一个事件:

To answer your question of how to communicate, you probably want to use the event approach that you mentioned. First you need an event in your logic class:

public event Action<int> UpdateProgress;

就像函数一样调用:

if (UpdateProgress != null)
   UpdateProgress(10);

这使用 Action 泛型委托声明了一个新事件,这意味着侦听函数必须返回 void 并采用一个 int 作为参数.

This declares a new event using the Action generic delegate, which means the listening function has to return void and take one int as a parameter.

然后在您的表单代码中,您将拥有:

Then in your forms code, you'll have:

MyClass logic = new MyClass();
private void SomeFunction
{       
    logic.UpdateProgress += UpdateProgressBar;
}

private void UpdateProgressBar(int newProgress)
{
    progressBar1.BeginInvoke(new Action(() =>
    {
       progressBar1.Value = newProgress;
    }));
}

这将创建您的逻辑类的新实例,并分配函数UpdateProgressBar"以在您的逻辑类引发 UpdateProgressBar 事件时调用.该函数本身使用 Dispatcher.BeginInvoke,因为您的逻辑类可能不在 UI 线程上运行,您只能从该线程执行 UI 任务.

This creates a new instance of your logic class, and assigns the function "UpdateProgressBar" to be called whenever your logic class raises the UpdateProgressBar event. The function itself uses Dispatcher.BeginInvoke because your logic class is likely not running on the UI thread, and you can only do UI tasks from that thread.

这里发生了很多事情,所以如果我能为你澄清任何事情,请告诉我!

There is a lot going on here, so please let me know if I can clarify anything for you!

这篇关于如何与来自另一个类的 Form 控件通信?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆