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 Eccezione StackOverflow perché continua a creare riferimenti in un ciclo infinito.

Sono nuovo alle applicazioni della GUI. Come devo procedere?

È stato utile?

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 Pulsante per chiamare 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top