1

我在 C# 中创建了一个小型聊天应用程序,并作为控制台应用程序启动。但是我想使用 WPF 为它创建一个 GUI。它是一个以 , 等函数命名的类DanMessengerClientInitializeConnection()SendMessage(string msg)

我已经在 Visual Studio 中设计了 UI,它Window1默认在 Window1.xaml.cs 上创建了它的类。我为“发送”按钮创建了一个事件处理程序,它现在只将一些虚拟文本附加到文本区域。我的问题是,我应该如何从 WINdow1 类中调用 SendMessage() 函数?

我尝试在该类中创建对象,但由于我还需要从第一个类中访问文本框(即,当我收到消息时,更新文本框),添加对 Window1 类的引用会引发StackOverflow异常,因为它会不断创建无限循环中的引用。

我是 GUI 应用程序的新手。我应该如何进行?

4

2 回答 2

3

WPF 中显示数据的规范方法是将控件绑定到它(请参阅MSDN 中的数据绑定)。这可能需要您包装或重构您的 messenger 类,以便它公开可绑定的属性。例如,您的 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}" />

这假设 messenger 对象被设置为窗口的 DataContext,例如当窗口创建 messenger 时:

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

请注意,您的信使类必须实现 INotifyPropertyChanged 才能正常工作。还要注意 OneWay 绑定,这样如果用户编辑 TextBox,它就不会破坏 MessageText 属性。(您也可以使用 TextBlock,这样用户根本无法对其进行编辑。)

完成此设置后,WPF 将自动监视 _myMessenger.MessageText 属性中的更改,并在发生更改时更新 TextBox.Text(即收到消息时)。

最后,关于如何发送:只需传递文本:

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

使用 Name 属性来命名包含要发送的消息的文本框:

<TextBox Name="MyTextBox" />
于 2009-10-24T22:39:49.603 回答
0

只是为了扩展一下 itowlson 所说的内容:

我将从创建这样的界面开始:

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

实现此接口的类的行为应该非常简单。当收到一条消息时,它会被添加到MessageBuffer(可能前面有一个换行符)。要发送消息,请设置MessageToSend并调用SendMessage(),这也会将发送的消息添加到MessageBuffer。为了简单起见,我跳过了很多实现细节。

接下来,我将构建一个测试类来实现IMessagingClientINotifyPropertyChanged. 这个类实际上不需要做任何实际的事情:它很可能只是以随机间隔生成随机测试消息并更新MessageBuffer;此外,当SendMessage被调用时,它会清除MessageToSend并更新MessageBuffer

然后,我将代码添加到我的窗口以创建此类的一个实例并将其设置DataContext为。我将我的出站和入站绑定TextBox到,并连接到呼叫。 MessageToSendTextBlockMessageBufferButtonSendMessage

一旦我的 UI 与我的测试对象一起工作,我将构建另一个实现相同接口的类,只有这个类会创建一个私有DanMessengerClient对象,属性设置器可以与之互操作。然后我会让我的窗口创建这个对象的一个​​实例。

实际的消息传递客户端可能需要更复杂,例如,您可能想要实现一个LastMessageReceived属性,以便您可以对该文本执行一些特殊操作,例如将其放入ToolTip. 并且该MessageBuffer属性实际上可能需要以某种方式支持富文本。但这是一个很好的起点。

于 2009-10-24T23:42:30.537 回答