Representing an ongoing conversation in XAML and recording it

Will Pittenger 281 Reputation points
2023-10-16T15:37:53.73+00:00

I'm working on an application in WPF that will show on going conversations much like what you see here. The conversation could go back in history infinitely far back in time (or at least to when it started). I also want to save it to a file. As posts in the conversation get older, it might be worth allowing garbage collection to remove them from memory until the user tries to scroll that far back.

I also want a log file for the user to browse and search, if desired, with tools like GREP or PowerShell. Unfortunately, I don't think a human readable format will store enough information. So I may need a JSON log as well that I'd reload conversations from.

All this needs to be shown with XAML. If the conversation is too short, I'd like some filler for the space above (below?) the existing posts until the posts fill the window.

Any suggestions on how to implement that?

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,438 questions
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,685 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,353 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Hui Liu-MSFT 40,866 Reputation points Microsoft Vendor
    2023-10-17T08:14:11.37+00:00

    Hi,@Will Pittenger. Welcome to Microsoft Q&A.

    To represent an ongoing conversation in XAML and simultaneously record it for logging purposes, you could use a combination of XAML controls for the UI and a logging mechanism for data recording.

    Here's a basic example to get you started:

    <Window x:Class="ConversationLogDemo.MainWindow"
    ...
             Name="window"
            Title="MainWindow" Height="450" Width="800">
     <DockPanel>
            <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" >
                <TextBox x:Name="MessageInput" Height="30" Margin="5"  Width="700"/>
                <Button Content="Send" Margin="10" Height="30" Width="75" Click="OnSendMessageClicked"/>
            </StackPanel>
            <StackPanel Width="{Binding ElementName=window, Path=ActualWidth}" DockPanel.Dock="Top">
                <ScrollViewer >
                    <Grid x:Name="ConversationPanel" Margin="10" >
                        
                        <ListView ItemsSource="{Binding Conversations}">
                            <ListView.View>
                                <GridView>
                                    <GridViewColumn Header="Sender" DisplayMemberBinding="{Binding Sender}" />
                                    <GridViewColumn Header="Content" DisplayMemberBinding="{Binding Content}" />
                                    <GridViewColumn Header="Timestamp" DisplayMemberBinding="{Binding Timestamp}" />
                                </GridView>
                            </ListView.View>
                        </ListView>
                    </Grid>
                </ScrollViewer>
            </StackPanel>
    
            <Label Content="something fill the window" Background="AliceBlue"   />
            
           
        </DockPanel>
    </Window>
    

    Codebedhind:

    
    using System;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Windows;
    using Formatting = Newtonsoft.Json.Formatting;
    
    namespace ConversationLogDemo
    {
        public partial class MainWindow : Window
        {
            private ObservableCollection<Conversation> conversations = new ObservableCollection<Conversation>();
            public ObservableCollection<Conversation> Conversations
            {
                get { return conversations; }
                set { conversations = value; }
            }
            private string _logFilePath = "C:\\Users\\...\\conversationLog.json";
            public MainWindow()
            {
                InitializeComponent();
                DataContext = this;
    
                // Load previous conversations from the log file
                LoadPreviousConversations();
            }
            private void LoadPreviousConversations()
            {
                if (File.Exists(_logFilePath))
                {
                    try
                    {
                        
                        string[] lines = File.ReadAllLines(_logFilePath);
                        foreach (var line in lines)
                        {
                            Conversation conversation = Newtonsoft.Json.JsonConvert.DeserializeObject<Conversation>(line);
                            Conversations.Add(conversation);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"An error occurred while loading conversations: {ex.Message}");
                    }
                }
            }
    
            private void LogConversation(Conversation conversation)
            {
                string jsonConversation = Newtonsoft.Json.JsonConvert.SerializeObject(conversation);
    
                try
                {
                    
                    File.AppendAllText(_logFilePath, jsonConversation + Environment.NewLine);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"An error occurred while logging conversation: {ex.Message}");
                }
            }
            private void OnSendMessageClicked(object sender, RoutedEventArgs e)
            {
                Conversation message = new Conversation() { Content= MessageInput.Text,  Timestamp=DateTime.Now };
                conversations.Add(message);
                // DisplayConversation();
                LogConversation(message);
               
    
                MessageInput.Text = string.Empty;
            }
    
         
        }
        public class Conversation
        {
            public string Sender { get; set; }
            public DateTime Timestamp { get; set; }
            public string Content { get; set; }
        }
    
    }
    
    
    

    The result:

    enter image description here

    If you still have questions, please feel free to let me know. The problem will be better solved if more details are described (steps, error messages, and code to reproduce the problem).


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.