TextCtrl.xaml
<Grid>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Height="68">
<Button Width="100" Margin="10" Content="清除" x:Name="btnClear"/>
<Button Width="100" Margin="10" Content="恢复" x:Name="btnRecall"/>
</StackPanel>
</Grid>
TextCtrl.xaml.cs
public partial class TextCtrl : UserControl
{
public TextCtrl()
{
InitializeComponent();
this.btnClear.Click +=this.clearClick;
this.btnRecall.Click += this.recalClick;
}
public event Action<string,string> clearEvent;
public event Action<string,string> recallEvent;
public Action clear_delegate;
public Action recall_delegate;
private void clearClick(object sender, RoutedEventArgs e)
{
if (clearEvent != null) { clearEvent("clear", "event"); }//没有Invoke()方法
if (clear_delegate != null) { clear_delegate.Invoke(); }//有Invoke()方法
}
private void recalClick(object sender, RoutedEventArgs e)
{
if (recallEvent != null) { recallEvent("recall","event"); }//没有Invoke()方法
if (recall_delegate != null) { recall_delegate.Invoke(); }//有Invoke()方法
}
}
MainWindow.xaml
<Grid>
<StackPanel Orientation="Vertical" >
<TextBox Width="200" Height="45" HorizontalAlignment="left" Margin="10" x:Name="txtBox" />
<local:TextCtrl HorizontalAlignment="Left" Margin="10 0 10 0" x:Name="textCtrl"/>
<TextBlock x:Name="txtBlock" Height="Auto" Width="Auto" Foreground="Red" FontSize="14"/>
</StackPanel>
</Grid>
MainWindwo.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.textCtrl.clearEvent += TextCtrl_clearEvent;
this.textCtrl.recallEvent += TextCtrl_recallEvent;
// this.textCtrl.clearEvent += new Action<string,string> (TextCtrl_clearEvent);//也可以这么写
// this.textCtrl.recallEvent +=new Action<string,string>( TextCtrl_recallEvent);//也可以这么写
// this.textCtrl.clearEvent = TextCtrl_clearEvent; //报错
// this.textCtrl.recallEvent = TextCtrl_recallEvent; //报错
this.textCtrl.clear_delegate += textBlockClear;
this.textCtrl.recall_delegate += textBlockRecall;
// this.textCtrl.clear_delegate += new Action(textBlockClear);//也可以这么写
//this.textCtrl.recall_delegate += new Action(textBlockRecall);//也可以这么写
// this.textCtrl.clear_delegate = textBlockClear;//不报错
// this.textCtrl.recall_delegate = textBlockRecall;//不报错
}
private string text;
public string Text
{ get
{
return text;
}
set{
text = value;
}
}
private void TextCtrl_recallEvent(string arg1, string arg2)
{
txtBox.Text = Text;
}
private void TextCtrl_clearEvent(string arg1, string arg2)
{
Text = txtBox.Text;
txtBox.Clear();
}
private void textBlockClear()
{
txtBlock.Text = "Clear";
}
private void textBlockRecall()
{
txtBlock.Text = "Recall";
}
}
イベントによって変更された後、このカスタムイベントをxamlに書き込むことができます
<local:TextCtrl HorizontalAlignment="Left" Margin="10 0 10 0" x:Name="textCtrl" clearEvent="TextCtrl_clearEvent" recallEvent="TextCtrl_recallEvent"/>
実行結果:
説明部分:
1.委任の概念
1.コンセプト:デリゲート(委任、エージェント...):デリゲートは実際にはプログラム機能であり、その特別な機能は、デリゲートを使用してメソッドを表現することです。言い換えると、デリゲートはメソッドの代表であり、メソッドのポインターです。
int age = 10;年齢は実際には10の代表です。
コースmyCourse = new Course(); myCourseは特定のオブジェクトの代表です。
デリゲートタイプデリゲート変数=特定のメソッド(1つまたは複数の場合があります)。デリゲートメソッドの変数。
2.なぜ委任を使用するのですか?
たとえば、人生で何かをすることを想像してみてください。しかし、それを直接完了することはできません。しかし、私たちは他の人を通してそれを行うことができます。
I --->他の人(委任)--->何かをする
今の比較で、前の時代やmyCourseなどがなんらかの「静的データ」を表していることがわかりました。
デリゲートは「動作」、つまりメソッドを表します。
ソフトウェア開発でも同様の状況が発生します。つまり、動作(メソッド)を呼び出したいのですが、このメソッドはオブジェクトが異なるためです。
直接呼び出すことができない場合があり、デリゲートを使用できます。
通常の状況:オブジェクトAで、オブジェクトBが作成されます。この時点で、オブジェクトBにパブリックビヘイビアCがある場合、それをAで呼び出すことができます。
クラスA
{
B b =新しいB();
void MyMethod()
{ bC(); }
void NewMethod(){}
}
質問:BがAで動作NewMethodを呼び出したい場合は可能ですか?もちろん違います!しかし、それは委託を通じて可能です。
2.コミッションの基本的な使い方
1.デリゲートを宣言します(メソッドのプロトタイプを定義します:メソッドの戻り値タイプ、パラメータータイプ、およびメソッドの番号)
2.委員会に従って特定の方法を書く
3.デリゲート変数を作成します(デリゲートは参照タイプです)
4.デリゲート変数を、デリゲート定義に準拠する1つ以上の特定のメソッドに関連付けます。
5.デリゲート変数を介して特定のメソッドを使用します(メソッドを直接使用しないでください)
結論:変数を委任することにより、それに関連付けられた特定のメソッドを簡単に呼び出すことができます。
拡張:複数のメソッドを同時にデリゲート変数に関連付ける場合、デリゲート変数を使用すると、メソッドは、関連付けた順序で順番に呼び出されます。
上記は、私たちがしばしば「多方向委任またはマルチキャスト委任」と呼ぶものです。
利点:デリゲートとメソッドの関連付けを動的に増やすだけでなく、メソッドの関連付けを動的に削除することもできます。
3.委託された実際の戦闘アプリケーション(1):マルチフォーム通信での使用
1.メインフォームAでは、サブフォームBのいくつかのオブジェクトが作成されます。
ここで、フォームBはAのメソッドを呼び出す必要があります。通常、これは不可能です。しかし、それは委任を通じて達成することができます。
2.ヒント:デリゲートを使用してタスクを完了する場合、デリゲート変数を定義する秘訣は、使用する場所で定義することです。(誰が誰を作成するか)
委任された変数と特定のメソッドの間の関連付けは、通常、別個のものです。一般に、関連付けは特定のメソッドが定義されている場所で行われます。
总結:B1-> A B2-> A B3-> A
拡張:委任を通じてメッセージのブロードキャストを実現する方法は?
メッセージの受信場所、メッセージの受信方法をどこに書いてください!これがフォームBです。
4、委託された実際の戦闘アプリケーション(2):コンテナがフォームに埋め込まれているときの切り替えの問題を解決するため
5.イベント(デリゲートと比較)
1つだけ見つけてください:this.btnCreateChildForm.Click + = new System.EventHandler(this.btnCreateChildForm_Click);
パブリックイベントEventHandlerクリック
パブリックデリゲートvoidEventHandler(オブジェクト送信者、EventArgs e);
ボタンのイベントを観察することにより、イベントが実際にはデリゲートのさらなるパッケージであることがわかりました。
イベントを定義する:(コードを直接見てください)この場合、以前と同じ機能を実現しますが、今回はイベントを使用します。
イベントの概念:イベントは、実際には、オブジェクトによる外部情報の刺激によって生成されるメッセージ応答メカニズムです。
エッセンス:このイベントは、実際には代表団のさらなるパッケージ化です。
イベントの参加者:
[1]送信者:オブジェクト自体です。情報ステータスが変更されると、イベントがトリガーされ、すべての受信者に受信するように通知されます。
passMsgEvent(this.txtSendMsg.Text、this.Text);
[2]レシーバー(レシーバー):イベントハンドラーです。このコードは、イベントセンダーがトリガーされた後に自動的に実行されます。
private void ReceiveMsg(string msg、string childName)
{ this.txtContent.Text + = $ "来自:{childName}的消息:{msg} \ r \ n"; }
イベントとデリゲートの違い:
まず、event = nullなどのイベントを直接割り当てることはできません。コンパイルエラーが発生しますが、デリゲートは割り当てることができます。
利点:クリックイベントなどのイベントをユーザーが直接操作することは避けてください。Click= nullが許可されている場合、基になるコードはクリアされます。保護的な役割を果たすことができます。
コミッショニングは比較的「オープン」すぎます。
次に、イベントオブジェクトにはinvoke()メソッドがなく、括弧を使用してのみ実行できます。
代表者とイベントの選択:
まず、問題を正常に解決するために、デリゲートとイベントの使用に本質的な違いはありません。したがって、委任を使用することをお勧めします。
次に、コントロールの二次開発を行い、コントロールのイベントを拡張する場合は、イベントを使用する必要があります。