Pregunta

He creado una pequeña aplicación de chat en C # y comencé como una aplicación de consola. Sin embargo, quiero crear una GUI para ello usando WPF. Es una clase llamada DanMessengerClient con funciones como InitializeConnection () , SendMessage (string msg) , etc.

Ya he diseñado la IU en Visual Studio, y creó su clase Window1 en Window1.xaml.cs de forma predeterminada. Creé un controlador de eventos para el " Enviar " botón que solo agrega un texto de relleno a un área de texto a partir de ahora. Mi pregunta es, ¿cómo debo llamar a la función SendMessage () desde la clase WIndow1?

Intenté crear el objeto en esa clase, pero como también necesito acceder al cuadro de texto desde la primera clase (es decir, cuando recibo un mensaje, actualizo el cuadro de texto), agregando la referencia a la clase Window1 arroja un StackOverflow excepción porque sigue creando referencias en un bucle infinito.

Soy nuevo en las aplicaciones GUI. ¿Cómo debo proceder?

¿Fue útil?

Solución

La forma canónica en WPF de mostrar datos es vincularlo a un control (consulte Enlace de datos en MSDN). Es probable que esto requiera que ajuste o refactorice su clase de mensajería para que exponga las propiedades enlazables. Por ejemplo, su clase de mensajería podría exponer una propiedad llamada MessageText, que actualiza cada vez que recibe un mensaje:

// 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;
}

Ahora enlazaría la propiedad TextBox.Text a esta nueva propiedad:

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

Esto supone que el objeto de mensajería está configurado como DataContext de la ventana, por ejemplo. cuando la ventana crea el mensajero:

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

Tenga en cuenta que su clase de mensajería debe implementar INotifyPropertyChanged para que esto funcione. También tenga en cuenta el enlace OneWay para que, si el usuario edita el TextBox, no se deshaga de la propiedad MessageText. (También puedes usar un TextBlock, para que el usuario no pueda editarlo en absoluto).

Cuando haya configurado esto, WPF supervisará automáticamente los cambios en la propiedad _myMessenger.MessageText, y actualizará el TextBox.Text a medida que ocurren (es decir, a medida que se reciben los mensajes).

Finalmente, sobre cómo hacer el envío: simplemente pase el texto:

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

Utilice el atributo Nombre para nombrar el cuadro de texto que contiene el mensaje que se enviará:

<TextBox Name="MyTextBox" />

Otros consejos

Solo para ampliar un poco lo que dice itowlson:

Empezaría creando una interfaz como esta:

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

El comportamiento de las clases que implementan esta interfaz debería ser bastante simple. Cuando se recibe un mensaje, se agrega a MessageBuffer (probablemente precedido por una nueva línea). Para enviar un mensaje, configure MessageToSend y llame a SendMessage () , que también agrega el mensaje enviado a MessageBuffer . Hay muchos detalles de implementación que me estoy saltando para mantener esto simple.

A continuación, crearía una clase de prueba que implementó IMessagingClient y INotifyPropertyChanged . Esta clase en realidad no tiene que hacer nada real: lo más probable es que solo produzca mensajes de prueba aleatorios a intervalos aleatorios y actualice MessageBuffer ; también, cuando se llama a SendMessage , se borraría MessageToSend y se actualizaría a MessageBuffer .

Luego agregaría un código a mi ventana para crear una instancia de esta clase y establecer el DataContext . Enlazaré mi TextBox de salida al MessageToSend y mi TextBlock de entrada al MessageBuffer , y conectaré un Botón para llamar a SendMessage .

Una vez que lograra que la interfaz de usuario funcionara con mi objeto de prueba, crearía otra clase que implementara las mismas interfaces, solo que esta crearía un objeto privado DanMessengerClient con el que los establecedores de propiedades interactuaron. Entonces haría que mi ventana creara una instancia de este objeto en su lugar.

Es probable que un cliente de mensajería real tenga que ser más sofisticado. Por ejemplo, es posible que desee implementar una propiedad LastMessageReceived para poder hacer algo especial con ese texto, como ponerlo en un ToolTip . Y la propiedad MessageBuffer en realidad podría necesitar que sea compatible con texto enriquecido de alguna manera. Pero este es un buen punto de partida.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top