2009-06-04 18 views
6

Tôi có một ứng dụng trong C# .net có MainForm và một vài lớp.
Một trong các lớp này nhận được thông báo dữ liệu đến từ mạng.
Tôi cần nhận được văn bản của tin nhắn này được thêm vào một hộp văn bản nhiều dòng trên MainForm.
Tôi có thể gửi thư đến một phương thức trong MainForm bằng cách đặt phương thức tĩnh, nhưng sau đó phương thức tĩnh không thể truy cập các điều khiển của MainForm.Trong C# .net, Làm thế nào để truy cập một điều khiển từ một phương pháp tĩnh?

TheIncomingDataClass.cs

namespace TheApplicationName 
{ 
    class TheIncomingDataClass 
    { 

    public void IncomingMessage(IncomingMessageType message) 
    { 
      TheApplicationName.MainForm.ReceiveMSG(message); 
    } 

MainForm.cs

public static void ReceiveMSG(string message) 
{ 
    txtDisplayMessages.AppendText(message); //This line causes compile error 
} 

Các lỗi biên dịch:
Một tham chiếu đối tượng là cần thiết cho TheApplicationName.MainForm.txtDisplayMessages không tĩnh lĩnh vực, phương pháp, hoặc tài sản' '

Mọi trợ giúp đều được đánh giá cao.

Tôi vẫn là người mới bắt đầu C# vì vậy hãy mô tả.

Trả lời

9

Phương thức tĩnh không có quyền truy cập vào các thành viên như txtDisplayMessages vì ​​nó không phải là một phần của cá thể đó. Tôi đề nghị bạn nên đọc một số khái niệm về các phương pháp tĩnh và không có điều gì, bởi vì đó là một khái niệm bất khả tri về ngôn ngữ khá. Phương pháp đó sẽ tốt nhất được phục vụ bằng cách loại bỏ công cụ sửa đổi tĩnh, vì nó không cần phải tĩnh - có vẻ như nó sẽ cần phải được gọi bởi cá thể cụ thể của đối tượng đó.

+0

Khi tôi xóa từ khóa tĩnh khỏi phương thức tôi không thể gọi nó từ Lớp IncomingData nữa. Tôi không hiểu ý bạn là gì bởi "được gọi bởi trường hợp cụ thể của đối tượng đó" bạn có thể giải thích thêm?hãy nhớ rằng tôi cần những tin nhắn này để được gửi đến hộp văn bản ngay lập tức khi nhận được chúng, vì vậy sự kiện sẽ là nhận được tin nhắn. Cảm ơn. – timmyg

+0

Tôi giả sử vì nó là tĩnh mà bạn đã gọi nó với MainForm. ReceiveMSG() [hoặc chỉ ReceiveMSG()]. Nó sẽ phải được gọi từ một thể hiện cụ thể của MainForm, (MainForm mf = new MainForm(); hoặc tương tự, để tạo ra một instnance). Sau đó, bạn có thể gọi nó là mf. ReceiveMSG(), thay thế mf bằng bất cứ thứ gì bạn đặt tên cho thể hiện của MainForm. Không có hành vi phạm tội, nhưng tôi nghĩ bạn cần đọc một số tài liệu ngôn ngữ bất khả tri về định hướng đối tượng, tìm hiểu ý nghĩa của tất cả điều này, và sau đó xem cách cú pháp C# liên quan đến nó như thế nào. – Annath

+0

Nghiêm túc, bạn nên lấy CLR Via C#. Nó dễ đọc (SKIP THE FIRST COUPLE OF CHAPTERS) và đi vào chi tiết tốt về điều này và hơn thế nữa! – Will

3

tăng sự kiện từ lớp mà biểu mẫu có thể đăng ký.

1

Chỉ cần xóa công cụ sửa đổi tĩnh, bạn không cần nó cho mục đích của mình. Đọc về số liệu thống kê here.

4

thể của nó để vượt qua trong một tham chiếu đến các hình thức hiện tại như thế này:

public static void ReceiveMSG(string message, MainForm mainform) 
{ 
    mainform.txtDisplayMessages.AppendText(message); 
} 

Mặc dù như đề nghị một sự kiện có lẽ là một cách tốt hơn để làm việc đó.

+0

Điều này không hiệu quả đối với tôi. Tôi đặt 'ReceiveMSG' bên trong một lớp khác và mặc dù' MainForm mainform' được khai báo là một tham số, tôi không thể truy cập các điều khiển của nó. – ellekaie

1

Bạn có thể giải quyết vấn đề này bằng cách xóa từ khóa tĩnh.

Khi bạn thấy "tĩnh", hãy suy nghĩ: không có trường hợp nào thuộc loại này.

Khi bạn gọi phương thức không tĩnh, bạn phải sử dụng rõ ràng một số phiên bản. Phương thức này có thể truy cập vào cá thể đó bằng cách sử dụng từ khóa "this".

Khi bạn gọi một phương thức tĩnh, không có trường hợp nào - bạn đã bỏ qua ranh giới của OO và hiện đang ở trong ngữ cảnh lập trình có cấu trúc hoặc chức năng. Nếu bạn muốn một thể hiện của một cái gì đó, bạn cần phải mang nó như một tham số.

1

Tôi nghĩ bạn có thể đang sử dụng sai phương pháp này. Có vẻ như bạn đang cố gắng đẩy tin nhắn cho khách hàng từ một quy trình bên ngoài. Có nhiều cách để làm điều này, nhưng nó sẽ trở nên phức tạp. Đề nghị của tôi sẽ là có cuộc thăm dò của khách hàng bất cứ điều gì quá trình có dữ liệu định kỳ - có thể mỗi 10 giây tùy thuộc vào nhu cầu của bạn. Đây sẽ là một heck dễ dàng hơn nhiều so với việc đẩy từ máy chủ đến máy khách.

+0

Jonathan - tại sao cuộc thăm dò ý kiến ​​tồi tệ hơn nếu anh ta sử dụng điều khiển từ xa? Theo như luồng, tôi không chắc chắn những gì bạn đang đề xuất phương pháp tiếp cận, nhưng hầu hết các đề xuất dưới đây dường như liên quan đến các sự kiện - nếu bạn sử dụng các sự kiện, bạn sẽ có cùng một vấn đề luồng. Vì anh ấy nói anh ấy là người mới bắt đầu, tôi chỉ đề xuất phương pháp đơn giản nhất sẽ hoạt động - tát bộ hẹn giờ trên đó và kiểm tra tin nhắn mới sau mỗi x giây. Nếu bạn định cập nhật ui, gọi lời gọi - bạn sẽ phải làm điều tương tự nếu bạn đi tuyến đường sự kiện. – Rob

+0

-Um, không, bộ hẹn giờ chạy trên một chuỗi khác. -Bạn đang giả định rằng nguồn dữ liệu trên cùng một máy, tác giả không bao giờ xác định điều đó. Ông chỉ đơn giản nói rằng nguồn là "tin nhắn dữ liệu đến từ một mạng" - điều này có thể là rất nhiều thứ khác nhau, nhưng ngụ ý rằng ít nhất, nguồn không nằm trong cùng một miền ứng dụng. Bây giờ - cho rằng tác giả có kinh nghiệm hạn chế và rằng anh ta đang xử lý w/giao tiếp với w/nhiều quy trình - bạn có nghĩ rằng anh ta sẽ hiểu cách tiêu thụ các sự kiện bị từ chối không? Chỉ cần cố gắng để ném ra một lựa chọn anh ta có thể không có suy nghĩ về điều đó sẽ được dễ dàng để làm. – Rob

+0

Tôi đã sửa chữa, tôi đã rút lại các nhận xét khác của mình. Tôi đã giả định rằng mã mạng của anh ta sẽ nằm trong cùng một AppDomain. Trong mọi trường hợp: : "Bộ hẹn giờ Windows này được thiết kế cho môi trường một luồng [...]" Giao diện người dùng của anh ta sẽ chặn. Nó thậm chí còn dễ dàng hơn để kiểm tra . –

5

Để tiếp tục cách bạn đã thực hiện, "TheIncomingDataClass" của bạn phải có tham chiếu đến đối tượng MainForm mà đối tượng sẽ giao diện. Khi bạn tạo một thể hiện của lớp này (có lẽ là từ một phương thức thể hiện của MainForm), bạn sẽ cần phải chuyển một tham chiếu tới đối tượng MainForm này.

class TheIncomingDataClass{ 
    MainForm form; 

    public TheIncomingDataClass(MainForm form){ 
     this.form = form; 
    } 
} 

class MainForm : Form{ 
    MainForm(){ 
     new TheIncomingDataClass(this); 
    } 
} 

Tuy nhiên, theo đề nghị của Bugs, bạn có lẽ sẽ tốt hơn làm cho này một sự kiện trên TheIncomingDataClass và đăng ký vào nó từ MainForm.

class IncomingMessageEventArgs : EventArgs{ 
    IncomingMessageType message; 

    public IncomingMessageType Message{get{return message;}} 

    public IncomingMessageEventArgs(IncomingMessageType message){ 
     this.message = message; 
    } 
} 

class TheIncomingDataClass{ 
    public event EventHandler<IncomingMessageEventArgs> MessageReceived; 

    protected virtual void OnMessageReceived(IncomingMessageEventArgs e){ 
     if(MessageReceived != null) 
      MessageReceived(this, e); 
    } 

    public void IncomingMessage(IncomingMessageType message){ 
     OnMessageReceived(new IncomingMessageEventArgs(message)); 
    } 
} 

class MainForm : Form{ 
    MainForm(){ 
     new TheIncomingDataClass().MessageReceived += 
      (s, e)=>txtDisplayMessages.AppendText(e.Message.ToString()); 
    } 
} 
+0

Tôi đang cố gắng sử dụng phương pháp của bạn và tất cả đều tốt ngoại trừ phần cuối cùng trong MainForm. "(s, e) => txtDisplayMessages.AppendText (e.Message.ToString());" Dòng mã này trả về nhiều lỗi biên dịch. Cụ thể là phần (s, e). – timmyg

1

Ok đây. Phương pháp tĩnh chỉ có thể truy cập các thành viên tĩnh. Phương thức ReceiveMSG của bạn là tĩnh. txtDisplayMessages không phải là và do đó bạn không thể truy cập nó. Tại sao phương pháp của bạn cần tĩnh? Không cần phải nói, nếu bạn xóa từ khóa tĩnh sẽ khắc phục sự cố của bạn.

Chỉ cần tạo phần ReceiveMSG của một lớp, tạo một thể hiện của lớp và sau đó gọi phương thức trên cá thể.

Tôi nghĩ bạn nên đăng loại giải pháp mà bạn đang mong đợi.

0

Thấy bạn mới sử dụng C# Tôi sẽ giữ điều này càng đơn giản càng tốt. Bạn nên có một tệp Program.cs có một phương thức Main (điều này có thể được tạo bởi Visual Studio). Bạn sẽ cần phải làm cho nó trông giống như sau:

class Program 
{ 
    public static readonly MainForm MainForm; 

    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     MainForm = new MainForm(); // These two lines 
     Application.Run(MainForm); // are the important ones. 
    } 
} 

Bây giờ trong thư đến của bạn, bạn sẽ có cách để truy cập biểu mẫu đó.

public void IncomingMessage(IncomingMessageType message) 
{ 
     Program.MainForm.RecieveMSG(message); 
} 

Phương thức đó trong biểu mẫu sau đó sẽ là phương pháp thể hiện (không tĩnh). Ví dụ.

public void RecieveMSG(IncomingMessageType message) // NB: No static 
{ 
    txtDisplayMessages.Text = message.Text; // Or whatever. 
} 

Có nhiều cách tốt hơn để làm điều đó - nhưng là người mới bắt đầu, tôi nghĩ đây sẽ là cách tiếp cận tốt nhất.

Sự khác biệt giữa tĩnh và ví dụ (ví dụ khi bạn không nói tĩnh) là rất lớn. Để có được một phương thức cá thể, trường hoặc thuộc tính (được gọi chung là các thành viên trong C#), bạn cần phải có cá thể chứa. Vì vậy:

Person p = new Person(); // You now have an instance. 
p.Name = "Fred"; // You are using an instance property. 

tĩnh là điều ngược lại, họ đều giống nhau ở bất cứ đâu trong ứng dụng của bạn (về mặt kỹ thuật hơn trong AppDomain cùng - nhưng nếu bạn là một người mới bắt đầu, bạn sẽ không cần phải lo lắng về điều đó trong một thời gian). Bạn không cần một cá thể để có được chúng (đạo cụ để codewidgets "Phương pháp tĩnh có thể truy cập chỉ các thành viên tĩnh"). Ví dụ:

// Where Planet is a class and People is a static property. 
// Somewhat confusingly the Add method is an instance - best left for the student :). 
Planet.People.Add(new Person("Fred")); 

Hy vọng rằng sẽ cho bạn một dấu hiệu tốt về tĩnh và thể hiện và nơi sử dụng chúng. Điều quan trọng nhất là cố gắng tránh các thành viên tĩnh tốt nhất có thể - chúng có thể gây ra những cơn ác mộng về bảo trì.

Microsoft có toàn bộ write-up về các khái niệm quan trọng liên quan đến vấn đề này.

+0

Làm thế nào để có một thành viên tĩnh tạo ra một cơn ác mộng bảo trì? – Rob

+0

Nó làm cho việc tái cấu trúc trở nên khó khăn hơn. Thời gian và thời gian một lần nữa tôi đã đào mình vào một lỗ với nó - đặc biệt là về luồng. Tốt nhất là hãy học cách làm việc mà không có quá nhiều thành viên tĩnh sớm. –

+0

Tôi đoán bạn có thể tạo ra một cơn ác mộng cho chính mình nếu bạn không hiểu OOD hoặc cách viết mã duy trì, nhưng đó sẽ là lỗi của nhà phát triển. Theo như luồng có liên quan, các nhà phát triển chỉ cần hiểu làm thế nào để viết mã an toàn thread. .Net có rất nhiều lớp học tốt để hỗ trợ việc này. Thành viên tĩnh có vị trí và sự hiểu biết của họ là rất quan trọng đối với một số mẫu thiết kế phần mềm rất quan trọng. Tôi sẽ không bao giờ nói với ai để tránh xa họ. – Rob

Các vấn đề liên quan