2011-06-10 56 views
0

我有一个简单的应用程序。这是它的工作原理。我有一个继承自Windows.Forms的类(MyForm)。它有一个按钮,一个标签和一个文本框。它看起来像一个聊天窗口。 还有另一个类(Cliente)需要一个字符串数组,它会为数组中的每个元素返回一个带有MyForm实例的List。事件处理程序和代表(简单问题)

我有第三类(Prueba),利用前两个类来测试它们。这个类创建MyForm的四个实例,并显示它们。 (我会省略一些代码和功能,因为我知道它工作正常。)

我需要能够在一个窗口中键入内容,并且当点击按钮时,它应该广播此消息并将其显示在所有其他视窗。 我知道我必须使用事件处理程序和代表,但经过几个小时的教程,我无法弄清楚要放哪里。

你能帮我吗?如果你能指点我一个很好的教程或例子就足够了,但如果你可以对我的代码更具体,它会很棒。 (我不知道如何让MyForm的一个实例知道其他实例,谁应该是这里的监听者?我在想客户端,但我不知道该怎么做)。 任何帮助将不胜感激!

//MyForm 
    namespace Dia26 { 

     //public delegate void ChangedEventHandler(object sender, EventArgs e); 

     public class MyForm : System.Windows.Forms.Form { 
      public Button btn = new Button(); 
      public TextBox textbox = new TextBox(); 
      public Label label = new Label(); 
      public Button btnEnviar = new Button(); 

      public delegate void OwnerChangedEventHandler(string newOwner); //~ 
      public event OwnerChangedEventHandler OwnerChanged; 

      protected void btn_Click(object sender, System.EventArgs e) { 
       this.Close(); 
      } 

      protected void btnEnviar_Click(object sender, System.EventArgs e) { 
       label.Text += textbox.Text + "\n"; 
       textbox.Text = ""; 
       if (this.OwnerChanged != null) { 
        this.OwnerChanged("something?"); 
       } 
      } 

      public MyForm() { 
       btn.Text = "cerrar"; 
       btn.Left = 400; 
       btn.Top = 280; 
       btn.Click += new EventHandler(this.btn_Click); 
       btnEnviar.Click += new EventHandler(this.btnEnviar_Click); 

       textbox.Left = 15; 
       textbox.Top = 20; 
       textbox.Width = 330; 

       label.Left = 15; 
       label.Top = 50; 
       label.AutoSize = false; 
       label.Height = 210; 
       label.Width = 450; 
       label.BackColor = Color.White; 

       btnEnviar.Left = 350; 
       btnEnviar.Top = 17; 
       btnEnviar.Text = "Enviar"; 

       this.Controls.Add(textbox); 
       this.Controls.Add(label); 
       this.Controls.Add(btn); 
       this.Controls.Add(btnEnviar); 

       this.SuspendLayout(); 
       this.Name = "MyForm"; 
       this.ResumeLayout(false); 

       return; 
      } 
     } 
    } 


    //Cliente.cs 
namespace Dia26Prueba { 
    public class Cliente { 
     public int creadas; 
     public int nocreadas; 

     public List<MyForm> MostrarVentanas(out bool error, ref int creadas, params string[] nombres) { 
      List<MyForm> list = new List<MyForm>(); 

      int bienCreadas = 0; 
      foreach (string str in nombres) { 
       if (str.Length >= 1) { 
        MyForm mf = new MyForm(); 
        mf.Text = str; 
        //mf.OwnerChanged += new OwnerChangedEventHandler(mf_OwnerChanged); 
        list.Add(mf); 
        mf.Show(); 
        bienCreadas++; 
       } 
      } 

      error = (bienCreadas == creadas); 
      nocreadas = bienCreadas - creadas; 
      creadas = bienCreadas; 

      return list; 
     } 

     public void ModificarPosicionYMedidas(MyForm mf, int x = 262, int y = 209, int width = 500, int height = 350) { 
      mf.Left = x; 
      mf.Top = y; 
      mf.Width = width; 
      mf.Height = height; 
     } 
    } 
} 

// Prueba 
namespace Dia29 { 
    class Prueba { 
     static void Main(string[] args) { 
      Cliente cliente = new Cliente(); 
      int n = 4; 

      Console.WriteLine(cliente.Autor); 

      if (args.Length != n) { 
       return; 
      } 

      int InstanciasCreadas = n; 
      bool HayErrores; 
      List<Dia26.MyForm> list; 

      list = cliente.MostrarVentanas(
       creadas: ref InstanciasCreadas, 
       error: out HayErrores, 
       nombres: new string[] { "FirstWindow", "2nd", "3rd", "4th" }); 

      cliente.ModificarPosicionYMedidas(list.ElementAt<MyForm>(0), 0, 0, 512, 384); 
      cliente.ModificarPosicionYMedidas(list.ElementAt<MyForm>(1), 512, 0, 512, 384); 
      cliente.ModificarPosicionYMedidas(list.ElementAt<MyForm>(2), 0, 384, 512, 384); 
      cliente.ModificarPosicionYMedidas(list.ElementAt<MyForm>(3), 512, 384, 512, 384); 

      for (int i = 0; i < n; i++) { 
       // ..... 
       Application.Run(list.ElementAt<MyForm>(i)); 
      }   


      Console.ReadLine(); 
     } 
    } 
} 

回答

0

这是一个小样本。我正在使用一个接口去除MainWindow和ChatWindows之间的耦合。

public class ChatEventArgs : EventArgs 
{ 
    public string ChatEventArgs(string message) 
    { 
     Message = message; 
    } 

    public string Message { get; private set; } 
} 


public interface IChatMessageProvider 
{ 
    event EventHandler<ChatEventArgs> MessageArrived; 
    void TriggerEvent(object source, ChatEventArgs args); 
} 

public class MainWindow : IChatMessageProvider 
{ 
    public event EventHandler<ChatEventArgs> MessageArrived = delegate{}; 

    public void AddChatWindow() 
    { 
     ChatWindow window = new ChatWindow(this); 
     window.Show(); 
    } 

    public void TriggerEvent(object source, ChatEventArgs args) 
    { 
     MessageArrived(source, args); 
    } 
} 

public class ChatWindow : 
{ 
    IChatMessageProvider _provider; 

    public ChatWindow(IChatMessageProvider provider) 
    { 
     _provider = provider; 
     provider.MessageArrived += OnMessage; 
    } 


    public void OnMesage(object source, ChatEventArgs args) 
    { 
     // since we could have sent the message 
     if (source == this) 
      return; 

     myListBox.Items.Add(args.Message); 
    } 

    public void SendButton_Click(object source, EventArgs e) 
    { 
     _provider.TriggerEvent(this, new ChatEventArgs(Textbox1.Text)); 
    } 
} 
+0

谢谢!我很感激! – Eric 2011-06-12 04:03:03

0
+0

我会,我已经在Java中使用它作为一个事实,唯一的问题是,我应该只使用原始事件处理程序和委托...任何其他想法? :) – Eric 2011-06-10 05:02:51

+0

链接中的示例确实使用事件处理程序和代理。你确定这不适合你? – alexD 2011-06-10 05:31:48

+0

事件本身就是观察者模式的实现。因此告诉使用Observer模式与告诉使用事件相同。 – Euphoric 2011-06-10 05:48:55

0

有actualy多种方式来做到这一点。

  • 只需在Cliente上制作方法,然后从Prueba中调用它。这是最简单和最直观的解决方案。
  • 将活动添加到Prueba,将Prueba的实例传递给Cliente,让Cliente注册参加此活动。
  • 使用某种全局静态消息类。无论是使用事件,还是简单的消息传递。