2009-10-24 69 views
1

我在C#中創建了一個小型聊天應用程序,並作爲控制檯應用程序啓動。不過,我想用WPF爲它創建一個GUI。這是一個與功能,如InitializeConnection()SendMessage(string msg)命名DanMessengerClient類等將控制檯應用程序移植到WPF

我已經設計在Visual Studio的用戶界面,它創造了它在默認情況下Window1.xaml.cs Window1類。我爲「發送」按鈕創建了一個事件處理程序,它只能將一些虛擬文本附加到textarea中。我的問題是,我應該如何從WIndow1類調用SendMessage()函數?

我嘗試在該類中創建對象,但由於我還需要從第一個類內部訪問文本框(即當我收到消息時,更新文本框),添加對Window1類的引用會引發StackOverflow異常,因爲它不斷在無限循環中創建引用。

我是新來的GUI應用程序。我應該如何繼續?

+1

爲什麼你需要課堂內的文本框?你的課只應該用於處理數據/給出結果,圖形用戶界面僅用於表示數據和結果。例如在你的按鈕處理程序中,你會做myMessengerClass.SendMessage(textBoxMessage.Text)。你的SendMessage方法應該知道如何處理接收到的文本,這樣你就不需要信使類中的文本框,只需要它的文本。 – Carlo

回答

3

WPF中顯示數據的規範方式是將控件綁定到它(請參閱MSDN中的Data Binding)。這可能需要你包裝或重構你的信使類,以便它公開可綁定的屬性。例如,你的信使類,就有可能暴露了一個名爲MessageText中的財產,你更新你每次收到一條消息:

// INotifyPropertyChanged interface implementation and plumbing 

public event PropertyChangedEventHandler PropertyChanged; 

protected virtual void OnPropertyChanged(string propertyName) 
{ 
    if (PropertyChanged != null) 
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName); 
} 

// The property you are going to bind to 

private string _messageText = String.Empty; 

public string MessageText 
{ 
    get { return _messageText; } 
    set 
    { 
    _messageText = value; 
    OnPropertyChanged("MessageText"); 
    } 
} 

// How to modify your code to update the bindable property 

private void OnMessageReceive(string message) // assuming this method already exists 
{ 
    MessageText = MessageText + Environment.NewLine + message; 
} 

現在,你將在TextBox.Text屬性綁定到這個新屬性:

<TextBox Text="{Binding MessageText, Mode=OneWay}" /> 

這假定信使對象被設置爲窗口的DataContext,例如當窗口創建信使:

public class Window1() 
{ 
    _myMessenger = = new DanMessengerClient(); 
    this.DataContext = _myMessenger; 
} 

注意你的信使類必須實現INotifyPropertyChanged才能工作。還請注意OneWay綁定,以便如果用戶編輯文本框,則不會消除MessageText屬性。 (您也可以使用TextBlock,以便用戶根本無法編輯它。)

當您設置此設置後,WPF將自動監視_myMessenger.MessageText屬性中的更改,並更新TextBox.Text發生時(即收到消息時)。

最後,關於如何做發送:只是通過文字:

private void SendButton_Click(...) 
{ 
    _myMessenger.Send(MyTextBox.Text); 
} 

使用name屬性來命名包含消息的文本框中發送:

<TextBox Name="MyTextBox" /> 
+0

該類非常小,我沒有任何編輯它的問題。不過,我不明白綁定如何幫助我。你能告訴我一個關於如何將字符串附加到文本框的例子嗎? –

+0

我假設你已經有類中的代碼來收到消息時做什麼,對吧?所以創建一個新的屬性,比如MessageText,最初是一個空字符串。現在,在您的接收代碼中,將接收到的文本追加到MessageText中,併爲MessageText引發PropertyChanged事件。這完成了對班級的更改。現在在您的XAML中,您設置了TextBox綁定和您的窗口DataContext,如上所示。現在,無論何時您的類更新MessageText,WPF都會注意到PropertyChanged事件並自動爲您更新TextBox。我將編輯以顯示更多細節。 – itowlson

+0

好的,我更新了代碼。請注意,我沒有將該字符串附加到TextBox。我將它附加到數據模型中的一個屬性*,並且文本框自動反映了這一點。這是慣用的WPF,並且需要_myMessenger來引用Window1或TextBox。 – itowlson

0

只是爲了擴大一下itowlson說什麼:

我會開始創建一個這樣的接口:

interface IMessagingClient 
{ 
    string MessageToSend { get; set; } 
    string MessageBuffer { get; } 
    void SendMessage(); 
} 

實現此接口的類的行爲應該非常簡單。收到消息時,它會被添加到MessageBuffer(可能前面有一個換行符)。要發送消息,請設置MessageToSend並呼叫SendMessage(),這也會將發送的消息添加到MessageBuffer。爲了簡單起見,我跳過了很多實現細節。

接下來,我會構建一個測試類,實現IMessagingClientINotifyPropertyChanged。這個類實際上並不需要做任何事情:它很可能只是隨機產生隨機測試消息並更新MessageBuffer;另外,當調用SendMessage時,它將清除MessageToSend和更新MessageBuffer

然後,我將代碼添加到我的窗口來創建此類的實例並將DataContext設置爲它。我會將我的外出TextBoxMessageToSend和我的入境TextBlockMessageBuffer,並掛鉤Button以致電SendMessage

一旦我的UI對我的測試對象起作用,我會構建一個實現相同接口的類,只有這個類纔會創建屬性設置器互操作的私有對象DanMessengerClient。然後,我會讓我的窗口創建此對象的一個​​實例。

實際的消息傳遞客戶端可能需要更復雜一些,例如,您可能想要實現LastMessageReceived屬性,以便您可以對該文本執行一些特殊的操作,例如將它放在ToolTip中。並且MessageBuffer屬性可能實際上需要以某種方式支持富文本。但這是一個很好的起點。

相關問題