Created
June 27, 2024 08:51
-
-
Save sappho192/14cfb1e4d0eef73ba56419a5715e6701 to your computer and use it in GitHub Desktop.
WPF FlowDocumentScrollViewer example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Window x:Class="WpfApp1.MainWindow" | |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |
xmlns:local="clr-namespace:WpfApp1" | |
mc:Ignorable="d" | |
Title="MainWindow" Height="450" Width="800"> | |
<Grid> | |
<FlowDocumentScrollViewer Name="ChatPanel" Block.LineHeight="2"> | |
<!--<RichTextBox x:Name="rtbChatlog1" IsReadOnly="True" > | |
<RichTextBox.ContextMenu> | |
<ContextMenu> | |
<MenuItem Header="복사" Command="ApplicationCommands.Copy"/> | |
<MenuItem Header="Custom Item" Click="MenuItem_Click"/> | |
</ContextMenu> | |
</RichTextBox.ContextMenu> | |
</RichTextBox>--> | |
</FlowDocumentScrollViewer> | |
</Grid> | |
</Window> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Text; | |
using System.Windows; | |
using System.Windows.Controls; | |
using System.Windows.Documents; | |
using System.Windows.Media; | |
namespace WpfApp1 | |
{ | |
/// <summary> | |
/// Interaction logic for MainWindow.xaml | |
/// </summary> | |
public partial class MainWindow : Window | |
{ | |
private FlowDocument _chatDocument; | |
public MainWindow() | |
{ | |
InitializeComponent(); | |
// Initialize the FlowDocument that will contain all chat messages | |
_chatDocument = new FlowDocument(); | |
ChatPanel.Document = _chatDocument; | |
} | |
private void AddMessage(string message) | |
{ | |
var paragraph = new Paragraph(new Run(message)) | |
{ | |
Foreground = Brushes.Blue, | |
FontWeight = FontWeights.Bold | |
}; | |
// Create and attach a custom context menu to the paragraph | |
var contextMenu = new ContextMenu(); | |
var menuItem = new MenuItem { Header = "Custom Action" }; | |
menuItem.Click += MenuItem_Click; | |
// Store the Paragraph object in the Tag property of the MenuItem | |
menuItem.Tag = paragraph; | |
contextMenu.Items.Add(menuItem); | |
var menuItemReplace = new MenuItem { Header = "Replace" }; | |
menuItemReplace.Click += MenuItemReplace_Click; | |
menuItemReplace.Tag = paragraph; | |
contextMenu.Items.Add(menuItemReplace); | |
paragraph.ContextMenu = contextMenu; | |
_chatDocument.Blocks.Add(paragraph); | |
} | |
private static int count = 1; | |
private void MenuItemReplace_Click(object sender, RoutedEventArgs e) | |
{ | |
// Retrieve the Paragraph object from the Tag property of the MenuItem | |
var paragraph = ((MenuItem)sender).Tag as Paragraph; | |
if (paragraph != null) | |
{ | |
string newMessage = $"replaced! ({count++})"; | |
ReplaceTextInParagraph(paragraph, newMessage); | |
MessageBox.Show($"Custom action triggered for paragraph: {newMessage}"); | |
} | |
} | |
private void MenuItem_Click(object sender, RoutedEventArgs e) | |
{ | |
// Retrieve the Paragraph object from the Tag property of the MenuItem | |
var paragraph = ((MenuItem)sender).Tag as Paragraph; | |
if (paragraph != null) | |
{ | |
string paragraphText = GetTextFromParagraph(paragraph); | |
MessageBox.Show($"Custom action triggered for paragraph: {paragraphText}"); | |
} | |
} | |
private string GetTextFromParagraph(Paragraph paragraph) | |
{ | |
StringBuilder sb = new StringBuilder(); | |
foreach (Inline inline in paragraph.Inlines) | |
{ | |
if (inline is Run run) | |
{ | |
sb.Append(run.Text); | |
} | |
else if (inline is Span span) | |
{ | |
foreach (Inline childInline in span.Inlines) | |
{ | |
if (childInline is Run childRun) | |
{ | |
sb.Append(childRun.Text); | |
} | |
} | |
} | |
// Handle other types of Inline elements if necessary | |
} | |
return sb.ToString(); | |
} | |
private void ReplaceTextInParagraph(Paragraph paragraph, string newText) | |
{ | |
// Clear existing inlines | |
paragraph.Inlines.Clear(); | |
// Add new text | |
paragraph.Inlines.Add(new Run(newText)); | |
} | |
protected override void OnContentRendered(EventArgs e) | |
{ | |
base.OnContentRendered(e); | |
// Example usage: Add multiple messages | |
for (int i = 0; i < 500; i++) | |
{ | |
AddMessage($"Lorem ipsum dolor sit amet, consectetur adipiscing elit. ({i + 1})"); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment