Search code examples
c#wpfbindingtextblocktwitch

Multiline text in dynamicaly changed TextBlock


Hi so i am trying to push a twitch chat into a TextBlock and it worked fine just using the mvvm with the textblock but now i want to actualy color the username and not sure how to make this multiline because the way i have it now it just replaces the previous message so i would need help to move forward. thanks!\

Xaml:

<TextBlock Grid.Column="1" Grid.Row="1" TextWrapping="Wrap" Background="Gainsboro" FontSize="14" Text="" Margin="5,5,5,5">
            <Run Text="{Binding Username, Mode=OneWay}" Foreground="{Binding UsernameColor, Mode=OneWay}" />
            <Run Text="{Binding Message, Mode=OneWay}" />
</TextBlock>

Event:

private void Client_OnMessageReceived(object sender, OnMessageReceivedArgs e)
        {
            Username = $"{e.ChatMessage.DisplayName}:";
            Message = e.ChatMessage.Message;
            UsernameColor = e.ChatMessage.ColorHex;
        }

so the issue is i want it to be multiline and not replace the Runs everytime a message comes thru.


Solution

  • I think you are following the wrong approach. You have to see a chat as a collection of messages. You want to display each message individually, as they come in. This shouts to use a ListBox where each item represents an individual message:

    ChatMessage.cs

    class ChatMessage : INotifyPropertyChanged
    {
      private string username;
      public string Username
      {
        get => this.username;
        set
        {
          this.username = value;
          OnPropertyChanged();
        }
      }
    
      private string message;
      public string Message
      {
        get => this.message;
        set
        {
          this.message = value;
          OnPropertyChanged();
        }
      }
    
      private string colorValue;
      public string ColorValue
      {
        get => this.colorValue;
        set
        {
          this.colorValue = value;
          OnPropertyChanged();
        }
      }
    
      public event PropertyChangedEventHandler PropertyChanged;
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
    }
    

    ViewModel.cs

    class ViewModel : INotifyPropertyChanged
    {
      public ObservableCollection<ChatMessage> Messages { get; set; }
    
      private void Client_OnMessageReceived(object sender, OnMessageReceivedArgs e)
      {
        var chatMessage = new ChatMessage
        { 
          Username = $"{e.ChatMessage.DisplayName}:",
          Message = e.ChatMessage.Message
          UsernameColor = e.ChatMessage.ColorHex
        }
        this.Messages.Add(chatMessage);
      }
    
      public event PropertyChangedEventHandler PropertyChanged;
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
    }
    

    MainWindow.xaml

    <Window>
      <Window.DataContext>
        <ViewModel />
      <Window.DataContext>
    
      <ListBox ItemsSource="{Binding Messages}"
               IsHitTestVisible="False">
        <ListBox.ItemTemplate>
          <DataTemplate DataType="{x:Type ChatMessage}">
            <StackPanel Orientation="Horizonatal">
              <TextBlock Text="{Binding Username}" 
                         Foreground="{Binding ColorValue}" />
              <TextBlock Text="{Binding Message}" />
            </StackPanel>
          </DataTemplate >
        </ListBox.ItemTemplate>
      </ListBox ItemsSource="{Binding Messages}">
    </Window>