Christian Klemm
Christian Klemm

Reputation: 1505

WPF Chatbox control

currently I'm working on a chat client and changed my client from windows forms (as forms is shitty) to WPF. I'm not really sure which control could be used to realize a chatbox. I could take a TextBox but this will not display the complete content when it's full. I also tried to use a ListBox but when I try to add items they are not displayed. I used this code to add content to it:

internal void AddMessage(string message)
{
    listBox_messages.Items.Add(message);
    listBox_messages.Items.Refresh();
}

Does anybody knows which control would be the best for this purpose?

Thanks for your help!

Edit: I implemented a TextBox for this and disabled it. But the text I'm appending by this method is not shown. My class:

using System.ComponentModel;
using System.Windows;

namespace Chat_Client
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// MainWindow constructor
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            textBox_messages.AppendText("Test" + "\n");
            textBox_messages.AppendText("Test" + "\n");
            textBox_messages.AppendText("Test" + "\n");

            Closing += OnWindowClosing;
        }

        private void OnWindowClosing(object sender, CancelEventArgs e)
        {
            Program.Shutdown();
        }

        private void button_connect_Click(object sender, RoutedEventArgs e)
        {
            if(Program.Connected)
            {
                Program.Disconnect();
            }
            else
            {
                Program.Connect();
            }            
        }

        private void button_sendMessage_Click(object sender, RoutedEventArgs e)
        {

        }

        internal void AddMessage(string message)
        {
            textBox_messages.AppendText(message + "\n");
        }
    }
}

The test strings are shown but the text added by the method AddMessage is not. I can verify that the method is called, I just checked it with a breakpoint inside this method. Anybody has a clue how this could happen?

Upvotes: 0

Views: 4095

Answers (3)

androo
androo

Reputation: 939

*In response to your edit: where are you calling AddMessage() from? I tried your code and just called AddMessage("foo"); from the button click event and worked fine.

For a chat box, I would use a TextBox to write the chat messages, and wrap it with a ScrollViewer for scrolling. After using AppendText() on the TextBox to write the message, you can then call ScrollToEnd() to scroll to the bottom of the TextBox.

In the XAML:

<ScrollViewer x:Name="ScrollViewer" ScrollChanged="ScrollViewer_OnScrollChanged"> <TextBox x:Name="ChatBox"/> </ScrollViewer>

In the code behind:

    private void WriteToChat(string message)
    {
        ChatBox.AppendText(message);
        ChatBox.ScrollToEnd();
    }

    private bool _autoScroll = true;
    private void ScrollViewer_OnScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        if (e.ExtentHeightChange == 0)
        {
            _autoScroll = ScrollViewer.VerticalOffset == ScrollViewer.ScrollableHeight;
        }

        if (_autoScroll && e.ExtentHeightChange != 0)
        {
            ScrollViewer.ScrollToVerticalOffset(ScrollViewer.ExtentHeight);
        }
    }

Upvotes: 2

El Cattivo
El Cattivo

Reputation: 180

Update

If the Program class calls AddMessage(string) from within another thread than the UI thread, you have to use a Dispatcher in order to update the UI.

Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
    mainWindow.AddMessage(message);
}));

MVVM is the way to go when using WPF.

  1. Add your messages to an ObservableCollection in your ViewModel class (ChatViewModel.cs):
public class ChatViewModel
{
    public ObservableCollection<string> Messages { get; } = new ObservableCollection<string>();

    internal void AddMessage(string message)
    {
        Messages.Add(message);
    }
}
  1. Set this ViewModel as the DataContext of your View (ChatView.xaml)
public ChatView : UserControl
{
    public ChatView()
    {
        InitializeComponent();
        DataContext = new ChatViewModel();
    }
}
  1. In the XAML-Code bind the ObservableCollection to the ItemsSource property of your ListBox:
<ListBox ItemsSource="{Binding Messages}") />

When you add a message to the Messages collection it should appear inside the ListBox. This is not a complete example, but it should guide you into the right direction.

Upvotes: 3

Amin Akhtar
Amin Akhtar

Reputation: 84

You can use a TextBox and set the VerticalAlignment to Stretch in your Xaml file.

< TextBox x:Name="textbox" VerticalAlignment="Stretch">

Upvotes: 0

Related Questions