控件,事件,委托,真的不清楚

unm 2004-06-26 07:10:10
Form中载入两个用户控件,一个控件中有一个Button A,一个控件中有一个TextBox B

我怎样在Form中用A的OnClick事件改变B的text,对事件和委托现在我真的不清楚。谢谢
...全文
221 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Bob 2004-06-27
  • 打赏
  • 举报
回复
http://dev.csdn.net/article/16/16260.shtm
Bob 2004-06-27
  • 打赏
  • 举报
回复

protected virtual void OnFailedThreeTimes(LoginEventArgs e)
{
if (FailedThreeTimes != null)
{
FailedThreeTimes(this, e);
}
}

protected virtual void OnCancel(System.EventArgs e)
{
if (Cancel != null)
{
Cancel(this, e);
}
}

private void btnLogin_Click(object sender, System.EventArgs e)
// 上面的定义是由VS.NET自动生成,是当按下控件的"btnLogin"按钮时调用的方法.
{
if(...)
OnGoodLogin(new LoginEventArgs(txtUserID.Text, txtPass.Text, true));
// 上面一行代码调用了OnGoodLogin方法,作用是"当控件中的按钮btnLogin被按下时,
// 并且符合上面的if条件时:
// 将通过调用OnGoodLogin方法把在用户代码中添加到事件"GoogLogin"中的所有方法
// 全部顺序执行一遍.
// 为什么不在这里把OnGoodLogin()方法中的代码执行一遍,而还要再单独调用OnGoodLogin
// 方法呢? 这是因为有时候用户代码需要重写OnGoodLogin()方法!
// 下面调用的OnFailedThreeTimes()方法和OnCancel()方法解释同上.
else
OnFailedThreeTimes(new LoginEventArgs(txtUserID.Text, txtPass.Text, false));
}

private void btnCancel_Click(object sender, System.EventArgs e)
{
OnCancel(new EventArgs());
}
}
}



回复人: syinter(丽台) ( ) 信誉:100 2002-11-12 13:20:00 得分:0


二.调用此控件的程序集(注意,此程序集是由VS.NET的"新建"->"Windows应用程序"生成的),也就是"用户代码"部分

namespace HostApp
{
public class Form1 : System.Windows.Forms.Form
{
private MyEventTEST.ActiveLogin activeLogin1;
// 上面一行代码引用了自定义控件库的类"ActiveLogin",并用它定义了一个对象"activeLogin1".
// 这里的"MyEventTEST"是在自定义的控件库中定义的命名空间,如果在这个程序集中没有出现
// "using MyEventTEST"语句,则该名称必须出现在对自定义控件引用的任何代码中!

private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
// 上面两个方法都是又VS.NET自动生成,不做另外解释.

private void InitializeComponent()
{
this.activeLogin1 = new MyEventTEST.ActiveLogin();
// 上面一行代码用自定义控件库中的类"ActiveLogin"实例化对象"activeLogin1"
this.SuspendLayout();

//
// activeLogin1
//
this.activeLogin1.Location = new System.Drawing.Point(144, 8);
this.activeLogin1.Name = "activeLogin1";
this.activeLogin1.Size = new System.Drawing.Size(280, 184);
this.activeLogin1.TabIndex = 0;

this.activeLogin1.GoodLogin += new MyEventTEST.GoodLoginEventHandler(this.activeLogin1_GoodLogin);
this.activeLogin1.Cancel += new System.EventHandler(this.activeLogin1_Cancel);
this.activeLogin1.FailedThreeTimes += new MyEventTEST.FailedThreeTimesEventHandler(this.activeLogin1_FailedThreeTimes);
// !!! 请注意上面的三行代码,这是用户代码接受自定义控件库中事件的代码 !!!
// 上面三行代码分别把用户定义的方法"activeLogin1_GoodLogin","activeLogin1_Cancel"
// 和"activeLogin1_FailedThreeTimes"分别添加到自定义控件中的事件"GoogLogin","Cancel"
// 和"FailedThreeTimes"中; 这样一来只要自定义控件中的对应事件一被激发,这些
// 添加用户自定义方法就会被执行.
// 要注意的是,用户自定义方法签名必须符合对应的多路委托的定义(因为事件是由多路委托
// 定义的,所以要添加到什么事件,定义就必须符合该事件对应的多路委托的定义)
// 而且,这里的Cancel事件类型是系统已经定义的多路委托"EventHandler"类型,所以它的实例化
// 与其它两个事件的实例化有所不同,是"System.EventHandler",而不是"MyEventTEST.EventHandler"!
// 这些用户自定义方法将在下面列出.
// 不过请注意,上面的三行代码虽然在方法InitializeComponent()中,但却是我们自己手工添加的!

//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(440, 357);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.activeLogin1,
});
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}

[STAThread]
static void Main()
{
Application.Run(new Form1());
}
// 上面的方法分别是Windows Forms程序的入口.

private void activeLogin1_GoodLogin(object sender, MyEventTEST.LoginEventArgs e)
{
MessageBox.Show("Good Login! " + e.UserID);
}

private void activeLogin1_FailedThreeTimes(object sender, MyEventTEST.LoginEventArgs e)
{
MessageBox.Show("Failed to login three times.");
}

private void activeLogin1_Cancel(object sender, System.EventArgs e)
{
MessageBox.Show("Cancel");
}
// 上面的三个方法(activeLogin1_GoogLogin,activeLogin1_Cancel和activeLogin1_FailedThreeTimes)
// 就是当自定义控件中对应的事件被激发时在当前程序集中对应的处理方法.
// 值得注意的是,签名应该完全符合对应的多路委托的定义!
}
}


Bob 2004-06-27
  • 打赏
  • 举报
回复
对.net framework"事件"理解比较透彻的C#代码分析
作  者: syinter (丽台)
等  级:
信 誉 值: 100
所属论坛: .NET技术 C#
问题点数: 1
回复次数: 17
发表时间: 2002-11-12 13:20:36



下面的文章是我自认为对"事件"机制理解比较透彻的后写的代码分析,但写完之后,鄙人又惟恐理解有所偏差,所以特贴出来让各位高手指教一二,若能让发现理解错误之处,将不胜感激(此问完全乃本人"独立自主"之作,绝非抄袭)

同时我相信此文对c#初学者也有一定帮助!

建议大家把文章粘贴到"记事本"中查看,这样看上舒服一些
因为代码比较长,所以分成两贴

为了阐述清晰,特举例说明;
该范例是在一个控件中完全自定义一组事件,并在另外的程序集中对事件被激发作出反映(也就是事件被激发后
调用预先定义好的方法).

一.含有自定义事件的控件主体代码及对应剖析 (注意,此控件库是由VS.NET的"新建"->"Windows控件库"生成的)

namespace MyEventTEST
{
public class LoginEventArgs : System.EventArgs
// 上面代码定义了在主程序中引发事件时需要传递给主程序的所有信息,并且注意,
// 该类必须派生于System.EventArgs类
{
public LoginEventArgs(string sUserID, string sPassword, bool bValid)
{
UserID = sUserID;
Password = sPassword;
Valid = bValid;
}

public string UserID;
public string Password;
public bool Valid;
}

public delegate void GoodLoginEventHandler(object sender, LoginEventArgs e);
public delegate void FailedThreeTimesEventHandler(object sender, LoginEventArgs e);
// 上面两行代码定义了两个多路委托(因此返回类型必须为void),每个委托对应一种类型的事件;
// 因为是多路委托,所以每个委托中可以含有多个方法.
// 请注意,参数是(object sender, LoginEventArgs e),所以添加到多路委托的方法必须符合这种签名方式.
// 此外,为什么这里不使用系统已经定义的多路委托"System.EventHandler(object sender, EventArgs e)",
// 而要自己定义新的委托"?????EventHandler()"呢?这是因为我们这里传递给用户程序集的参数不是
// "System.EventArgs"类型,而是自己定义的"LoginEventArgs"类型,所以有必要重新定义自己的委托类型.


public class ActiveLogin : System.Windows.Forms.UserControl
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txtUserID;
private System.Windows.Forms.TextBox txtPass;
private System.Windows.Forms.Button btnLogin;
private System.Windows.Forms.Button btnCancel;
private System.ComponentModel.Container components = null;
// 上面代码是组成这个控件的一些组件定义,由VS.NET自动生成

public event GoodLoginEventHandler GoodLogin;
public event FailedThreeTimesEventHandler FailedThreeTimes;
public event EventHandler Cancel;
// 上面三行代码非常之重要,定义了三个事件(event),分别是"GoodLogin","FailedThreeTimes"
// 和"Cancel"
// 它们的类型分别是"GoodLoginEventHandler","FailedThreeTimesEventHandler"
// 和"EventHandler",也就是说添加到这三个事件中的方法必须符合对应的多路委托定义!
// 而且注意,因为事件"Cancel"的类型是系统已经定义的多路委托"EventHandler"类型,
// 所以上面的多路委托中没有定义类似"CancelEventHandler"的新委托,因为是不需要的.

public ActiveLogin()
{
InitializeComponent();
}
// 上面代码是控件中类"ActiveLogin"的构造方法,该方法中调用了初始方法InitializeComponent()
// 上面代码由VS.NET自动生成

protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
// 上面代码是自定义控件中类"ActiveLogin"的析构方法,由VS.NET自动生成.

private void InitializeComponent()
{
.... // 这里是对所有引用控件(组件)的初始化代码
}
// 上面代码是自定义控件中类"ActiveLogin"的初始方法,其中内容由VS.NET自动生成.

protected virtual void OnGoodLogin(LoginEventArgs e)
// 上面一行代码定义了激发"GoodLogin"事件的方法;
// 注意签名类型,定义方法是protected virtual,也就是说只能在这个类及它的
// 继承类中访问此方法,而且可以重写.
// 参数类型是"LoginEventArgs",注意只有这一个参数,因为在本方法中含有对
// this的引用,所以这里不需要传递this对象.
// 一般地说,这个方法使用场合只有两种:
// <1>在本控件内被调用,因为本方法不被调用,就无法激发用户代码在事件"GoodLogin"
// 中添加的方法;
// <2>在用户的继承代码中重写本方法,虽然重写本方法可能会带来性能的提高,但
// 倘若用户代码中忘记调用此方法,那么在用户代码先前在事件"GoodLogin"中
// 添加的方法将无法得到激活!!! (避免此问题的方法就是在重写方法中必须含有
// 一行"base.GoogLogin(e)",这行将负责调用本方法)
// 对于第<2>点需要提出的是,在用户的继承代码中重写本方法的作用相当与在
// 事件"GoodLogin"中添加一个方法,此方法的代码内容和重写方法内容相同.
// (但是应该绝对没有"base.GoogLogin(e)"这一行)
{
if (GoodLogin != null) // 如果在事件"GoogLogin"中含有方法,则激发这些方法
{
GoodLogin(this, e); // 把this对象和参数e传递给所有在事件"GoogLogin"
// 中添加的方法,并顺序执行这些方法 (注意,由多路
// 委托特性决定:在用户代码中先添加的方法先执行.
}
}
// 上面对OnGoogLogin方法解释已经十分详细了,下面两个ON方法均与上述ON方法同出一辙.
社会栋梁 2004-06-27
  • 打赏
  • 举报
回复
来学习
marvelstack 2004-06-27
  • 打赏
  • 举报
回复
namespace ConsoleTest
{
delegate void delegate1(string str);
delegate void delegate2(int dd);
class ZZConsole
{
[STAThread]
static void Main(string[] args)
{
delegate1 d1= new delegate1(StrMethod);
delegate2 d2= new delegate2(IntMethod);
d1("委托包装字符串方法");
d2(111111);

Console.ReadLine();
}
public static void StrMethod(string str)
{
Console.WriteLine(str);
}
public static void IntMethod(int dd)
{
Console.WriteLine(dd.ToString());
}

}
}

委托可以看作安全的函数指针;
写一个函数
public string GetValue(int i)
{
i.ToString();
}
//定义委托
delegate string GetValuehandler(int i);
//使用安全包装
GetValuehandler mydele = new GetValuehandler(GetValue);
//执行
string s = mydele(99);
相当于执行了
string s = GetValuehandler(99);
unm 2004-06-27
  • 打赏
  • 举报
回复
哪位可以解释一下这句话:
如果你有一个代表实例和一个适当的参数集合,你就可以用参数来调用这个代表。 代表的一个有趣而又有用的特性是它不知道或不关心它引用的对象的类。只要方法的签名与代表的签名一致,任何对象都可以作。这使得代表适合作“匿名“调用”。

如何理解:用参数来调用这个代表
如何理解:适合作“匿名“调用”

能否给一个贴切的实例?

谢谢
unm 2004-06-26
  • 打赏
  • 举报
回复
无论在哪里,如何在A的事件中处理B的Text属性?
现在情况是这样的:
一个Form,用代码动态载入两个用户控件
一个用户控件里有一个Button
一个用户控件里有一个TextBox,这个用户控件已经加入属性:

public string textBoxValue
{
set
{
this.textBox1.Text = value;
}
}


如何在A的事件中给textBoxValue赋值?
谢谢大侠了!
wolftop 2004-06-26
  • 打赏
  • 举报
回复
foreach(Control ct in this.ActiveControl)
{
if(ct is TextBox)
{
ct.Text ="你要改变的文本";
}
}
wolftop 2004-06-26
  • 打赏
  • 举报
回复
b.text
unm 2004-06-26
  • 打赏
  • 举报
回复
还有,如何在A的事件中改变B的text?应为它们都是动态载入的,所以,如何在A中找B的Text属性?

110,545

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧