Porting di un'applicazione console su WPF
Domanda
Ho creato una piccola applicazione di chat in C # e ho iniziato come Applicazione console. Tuttavia, voglio creare una GUI per esso utilizzando WPF. È una classe chiamata DanMessengerClient
con funzioni come InitializeConnection ()
, SendMessage (string msg)
, ecc.
Ho già progettato l'interfaccia utente in Visual Studio e per impostazione predefinita ha creato la sua classe Window1
su Window1.xaml.cs. Ho creato un gestore eventi per " Invia " pulsante che aggiunge solo un po 'di testo fittizio a un'area di testo a partire da ora. La mia domanda è: come dovrei chiamare la funzione SendMessage () dalla classe WIndow1?
Ho provato a creare l'oggetto in quella classe, ma poiché ho anche bisogno di accedere alla casella di testo dall'interno della prima classe (cioè quando ricevo un messaggio, aggiorno la casella di testo), l'aggiunta del riferimento alla classe Window1 genera un
Sono nuovo alle applicazioni della GUI. Come devo procedere?
Soluzione
Il modo canonico in WPF per visualizzare i dati è quello di associare un controllo ad esso (vedere Data Binding in MSDN). Ciò richiederebbe probabilmente che tu impacchi o rifatti la tua classe messenger in modo che esponga proprietà vincolanti. Ad esempio, la tua classe messenger potrebbe esporre una proprietà chiamata MessageText, che aggiorni ogni volta che ricevi un messaggio:
// 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;
}
Ora associ la proprietà TextBox.Text a questa nuova proprietà:
<TextBox Text="{Binding MessageText, Mode=OneWay}" />
Ciò presuppone che l'oggetto messenger sia impostato come DataContext della finestra, ad es. quando la finestra crea il messenger:
public class Window1()
{
_myMessenger = = new DanMessengerClient();
this.DataContext = _myMessenger;
}
Nota che la tua classe messenger deve implementare INotifyPropertyChanged affinché funzioni. Si noti inoltre l'associazione OneWay in modo che se l'utente modifica la TextBox non impantanerà la proprietà MessageText. (Puoi anche usare un TextBlock, in modo che l'utente non possa modificarlo affatto.)
Quando hai impostato questo, WPF monitorerà automaticamente le modifiche nella proprietà _myMessenger.MessageText e aggiornerà il TextBox.Text nel momento in cui si verificano (cioè quando i messaggi vengono ricevuti).
Infine, riguardo a come effettuare l'invio: basta passare il testo:
private void SendButton_Click(...)
{
_myMessenger.Send(MyTextBox.Text);
}
Utilizzare l'attributo Nome per assegnare un nome alla casella di testo contenente il messaggio da inviare:
<TextBox Name="MyTextBox" />
Altri suggerimenti
Solo per espandere un po 'quello che dice itowlson:
Comincerei creando un'interfaccia come questa:
interface IMessagingClient
{
string MessageToSend { get; set; }
string MessageBuffer { get; }
void SendMessage();
}
Il comportamento delle classi che implementano questa interfaccia dovrebbe essere piuttosto semplice. Quando viene ricevuto un messaggio, questo viene aggiunto a MessageBuffer
(probabilmente preceduto da una nuova riga). Per inviare un messaggio, imposta MessageToSend
e chiama SendMessage ()
, che aggiunge anche il messaggio inviato a MessageBuffer
. Ci sono molti dettagli di implementazione che sto saltando per mantenerlo semplice.
Successivamente, creerei una classe di test che implementasse IMessagingClient
e INotifyPropertyChanged
. Questa classe in realtà non deve fare nulla di reale: molto probabilmente produrrebbe semplicemente messaggi di test casuali a intervalli casuali e aggiornerebbe MessageBuffer
; inoltre, quando viene chiamato SendMessage
, si cancella MessageToSend
e si aggiorna MessageBuffer
.
Quindi aggiungerei il codice alla mia finestra per creare un'istanza di questa classe e impostare DataContext
su di essa. Vorrei associare il mio TextBox
in uscita a MessageToSend
e il mio TextBlock
in entrata a MessageBuffer
e collegare un SendMessage
.
Una volta che l'interfaccia utente funzionava con il mio oggetto test, creavo un'altra classe che implementava le stesse interfacce, solo questa creava un oggetto DanMessengerClient
privato con cui i setter di proprietà interagivano. Quindi farei in modo che la mia finestra crei un'istanza di questo oggetto.
Probabilmente un client di messaggistica reale dovrà essere più sofisticato, ad esempio, potresti voler implementare una proprietà LastMessageReceived
in modo da poter fare qualcosa di speciale con quel testo, come inserirlo un suggerimento
. E la proprietà MessageBuffer
potrebbe effettivamente aver bisogno di supportare il rich text in qualche modo. Ma questo è un buon punto di partenza.