I have created a small chatting application in C#, and started as a Console Application. However I want to create a GUI for it using WPF. It's a class named DanMessengerClient
with functions such as InitializeConnection()
, SendMessage(string msg)
, etc.
I have already designed the UI in Visual Studio, and it created it's Window1
class on Window1.xaml.cs by default. I created an event handler for the "Send" button that only appends some dummy text to a textarea as of now. My question is, how should I call the SendMessage() function from the WIndow1 class?
I tried creating the object in that class, but since I also need to access the Textbox from inside the first class (ie When I recieve a message, update the textbox), adding the reference to the Window1 class throws a StackOverflow
exception because it keeps creating references in an infinite loop.
I'm new to GUI applications. How should I proceed?
The canonical way in WPF to display data is to bind a control to it (see Data Binding in MSDN). This would probably require that you wrap or refactor your messenger class so that it exposes bindable properties. For example, your messenger class might expose a property called MessageText, which you update every time you receive a message:
// 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;
}
Now you would bind the TextBox.Text property to this new property:
<TextBox Text="{Binding MessageText, Mode=OneWay}" />
This assumes that the messenger object is set as the window's DataContext, eg when the window creates the messenger:
public class Window1()
{
_myMessenger = = new DanMessengerClient();
this.DataContext = _myMessenger;
}
Note your messenger class must implement INotifyPropertyChanged for this to work. Also note the OneWay binding so that if the user edits the TextBox it doesn't muck up the MessageText property. (You could also use a TextBlock, so that the user couldn't edit it at all.)
When you've got this set up, WPF will automatically monitor for changes in the _myMessenger.MessageText property, and update the TextBox.Text as they happen (ie as messages are received).
Finally, regarding how to do the send: just pass the text:
private void SendButton_Click(...)
{
_myMessenger.Send(MyTextBox.Text);
}
Use the Name attribute to name the text box containing the message to be sent:
<TextBox Name="MyTextBox" />
Just to expand a bit on what itowlson is saying:
I'd start by creating an interface like this:
interface IMessagingClient
{
string MessageToSend { get; set; }
string MessageBuffer { get; }
void SendMessage();
}
The behavior of classes implementing this interface should be pretty simple. When a message is received, it gets added to MessageBuffer
(probably preceded by a newline). To send a message, set MessageToSend
and call SendMessage()
, which also adds the sent message to MessageBuffer
. There are a lot of implementation details I'm skipping to keep this simple.
Next, I'd build a test class that implemented IMessagingClient
and INotifyPropertyChanged
. This class doesn't actually have to do anything real: it would most likely just produce random test messages at random intervals and update MessageBuffer
; also, when SendMessage
is called, it would clear MessageToSend
and update MessageBuffer
.
I'd then add code to my window to create an instance of this class and set the DataContext
to it. I'd bind my outbound TextBox
to MessageToSend
and my inbound TextBlock
to MessageBuffer
, and hook up a Button
to call SendMessage
.
Once I got the UI working against my test object, I'd build a another class that implemented the same interfaces, only this one would create a private DanMessengerClient
object that the property setters interoperated with. Then I'd make my window create an instance of this object instead.
An actual messaging client is probably going to need to be more sophisticated, For instance, you might want to implement a LastMessageReceived
property so that you can do something special with that text, like put it in a ToolTip
. And the MessageBuffer
property might actually need to support rich text in some way. But this is a good starting point.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.