문제

C#에서 작은 채팅 응용 프로그램을 만들었고 콘솔 응용 프로그램으로 시작했습니다. 그러나 WPF를 사용하여 GUI를 만들고 싶습니다. 이름이 지정된 수업입니다 DanMessengerClient다음과 같은 기능으로 InitializeConnection(), SendMessage(string msg), 등.

나는 이미 Visual Studio에서 UI를 설계했으며 그것을 만들었습니다. Window1 Window1.xaml.cs의 클래스 기본적으로 클래스. "보내기"버튼에 대한 이벤트 핸들러를 만들었습니다. 내 질문은 Window1 클래스에서 sendMessage () 함수를 어떻게 호출해야합니까?

해당 클래스에서 객체를 만들려고 시도했지만 첫 번째 클래스 내부에서 텍스트 상자에 액세스해야하기 때문에 (예 : 메시지를받을 때, 텍스트 상자를 업데이트) Window1 클래스에 대한 참조를 추가하면 a. StackOverflow 무한 루프에서 참조를 계속 생성하기 때문에 예외.

GUI 애플리케이션을 처음 사용합니다. 어떻게 진행해야합니까?

도움이 되었습니까?

해결책

WPF의 표준 방식은 데이터를 표시하는 것입니다. 데이터 바인딩 MSDN). 이를 위해서는 메신저 클래스를 래핑하거나 리팩터링하여 바인딩 가능한 속성을 노출시켜야 할 것입니다. 예를 들어, Messenger 클래스는 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}" />

이것은 메신저 객체가 창의 데이터 콘텍스트로 설정되었다고 가정합니다. 예를 들어 창이 메신저를 생성 할 때 :

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

메신저 클래스는 이것이 작동하려면 inotifyPropertyChanged를 구현해야합니다. 또한 사용자가 텍스트 상자를 편집하면 MessageText 속성을 조롱하지 않도록 Oneway 바인딩에 유의하십시오. (사용자가 전혀 편집 할 수 없도록 텍스트 블록을 사용할 수도 있습니다.)

이 설정이 있으면 WPF는 _MyMESSENGER.MESSAGETEXT 속성의 변경 사항을 자동으로 모니터링하고 TextBox.Text가 발생할 때 (예 : 메시지 수신)를 업데이트합니다.

마지막으로 보내는 방법에 대해 : 텍스트를 전달하십시오.

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

이름 속성을 사용하여 보내야 할 메시지가 포함 된 텍스트 상자의 이름을 말하십시오.

<TextBox Name="MyTextBox" />

다른 팁

Itowlson이 말하는 내용을 조금 확장하기 위해 :

다음과 같은 인터페이스를 만드는 것으로 시작합니다.

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

이 인터페이스를 구현하는 클래스의 동작은 매우 간단해야합니다. 메시지가 수신되면 추가됩니다. MessageBuffer (아마도 Newline이있을 것입니다). 메시지를 보내려면 설정하십시오 MessageToSend 그리고 전화 SendMessage(), 보낸 메시지를 추가합니다 MessageBuffer. 이것을 간단하게 유지하기 위해 건너 뛰는 구현 세부 사항이 많이 있습니다.

다음으로 구현 된 테스트 클래스를 구축했습니다 IMessagingClient 그리고 INotifyPropertyChanged. 이 클래스는 실제로 실제 작업을 수행 할 필요가 없습니다. 무작위 간격으로 임의의 테스트 메시지를 생성하고 업데이트 할 가능성이 높습니다. MessageBuffer; 또한 언제 SendMessage 명확해질 것입니다 MessageToSend 그리고 업데이트 MessageBuffer.

그런 다음 내 창에 코드를 추가 하여이 클래스의 인스턴스를 만들고 DataContext 그것에. 나는 내 아웃 바운드를 묶어 놓았다 TextBox 에게 MessageToSend 그리고 내 인바운드 TextBlock 에게 MessageBuffer, 그리고 연결 a Button 전화합니다 SendMessage.

내 테스트 객체에 대해 UI가 작동하게되면 동일한 인터페이스를 구현 한 다른 클래스를 구축하면 개인 만 사용합니다. DanMessengerClient 속성 세터가 상호 운용 한 개체. 그런 다음 내 창이 대신이 객체의 인스턴스를 만듭니다.

실제 메시징 클라이언트는 아마도 더 정교해야 할 것입니다. 예를 들어, 당신은 LastMessageReceived 그 텍스트로 특별한 일을 할 수 있도록 속성은 ToolTip. 그리고 MessageBuffer 속성은 실제로 어떤 식 으로든 풍부한 텍스트를 지원해야 할 수도 있습니다. 그러나 이것은 좋은 출발점입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top