代码之家  ›  专栏  ›  技术社区  ›  Daniel Sorichetti

将控制台应用程序移植到WPF

  •  1
  • Daniel Sorichetti  · 技术社区  · 16 年前

    我用C语言创建了一个小的聊天应用程序,并作为控制台应用程序启动。不过,我想使用WPF为它创建一个GUI。这是一个名为 DanMessengerClient 具有以下功能: InitializeConnection() , SendMessage(string msg) 等。

    我已经在Visual Studio中设计了UI,它创建了 Window1 默认情况下,在window1.xaml.cs上初始化。我为“send”按钮创建了一个事件处理程序,从现在起它只将一些伪文本附加到文本区域。我的问题是, 我应该如何从window1类调用sendmessage()函数?

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

    我不熟悉图形用户界面应用程序。我该怎么办?

    2 回复  |  直到 16 年前
        1
  •  3
  •   itowlson    16 年前

    WPF中显示数据的标准方法是将控件绑定到它(请参见 Data Binding 在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;
    }
    

    注意,您的messenger类必须实现inotifyPropertyChanged才能使其工作。还要注意单向绑定,这样如果用户编辑文本框,它就不会弄脏messagetext属性。(您也可以使用文本块,这样用户就根本无法编辑它。)

    设置好后,wpf将自动监视mymessenger.messagetext属性中的更改,并在发生更改时(即收到消息时)更新textbox.text。

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

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

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

    <TextBox Name="MyTextBox" />
    
        2
  •  0
  •   Robert Rossney    16 年前

    只想稍微扩展一下伊托森的话:

    我先创建这样的接口:

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

    实现这个接口的类的行为应该非常简单。当接收到消息时,它将被添加到 MessageBuffer (可能前面有一个换行符)。要发送消息,请设置 MessageToSend 并打电话 SendMessage() ,它还将发送的消息添加到 消息缓冲区 . 为了保持这个简单,我跳过了很多实现细节。

    接下来,我将构建一个实现 IMessagingClient INotifyPropertyChanged . 这个类实际上不需要做任何实际的事情:它很可能只是以随机间隔生成随机测试消息并更新 消息缓冲区 此外,当 SendMessage 被称为 消息发送 更新 消息缓冲区 .

    然后我将向窗口添加代码以创建此类的实例并设置 DataContext 对它。我要把我的出境行李捆起来 TextBox 消息传递 和我的入境 TextBlock 消息缓冲区 勾起一个 Button 打电话 发送消息 .

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

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