优化用户控件和数据处理逻辑

在 `CodeSpanControl.xaml` 中,将布局从 `StackPanel` 更改为 `DockPanel`,并设置 `SelectableTextBlock` 的 `TextWrapping` 属性为 `Wrap`。调整按钮样式,增加 `DockPanel.Dock` 属性。

在 `MarkdownWpfRenderer.cs` 中,提升代码可读性,删除多余行。

修正 `PromptUtil.cs` 中的 XML 标签格式,确保时间和 Excel 文件列信息的正确性。

新增 `XamlToContentConverter` 类,用于将字符串形式的 XAML 转换为 UI 元素。

在 `AiMessageControll.xaml` 中,移除布尔值转换器的注释,增加多个 `TabItem` 以显示不同内容类型,并调整 `TextBox` 属性。

在 `ChatMessage.cs` 中,增加 `ContentXaml` 属性,确保内容更改时触发属性变化通知。

在 `ImportViewModel.cs` 中,调试模式下的 `promptedMsg` 变量替换为 `TEST_AI_CONTENT`,并增加新的测试内容字符串以展示 Markdown 功能。
This commit is contained in:
lihanbo 2025-03-06 18:00:26 +08:00
parent 7506d59b3b
commit 0793330ab2
8 changed files with 325 additions and 68 deletions

View File

@ -1,32 +1,39 @@
<UserControl x:Class="EleCho.MdViewer.Controls.CodeSpanControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:EleCho.MdViewer.Controls"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="160">
<StackPanel Orientation="Horizontal" Margin="5">
<local:SelectableTextBlock Text="{Binding Text}" VerticalAlignment="Center"/>
<Button x:Name="Copy"
Content="复制"
Click="Copy_Click"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Padding="4,0"
Opacity="1"
Height="20"
Background="#AAFFFFFF"
BorderThickness="1">
<UserControl
x:Class="EleCho.MdViewer.Controls.CodeSpanControl"
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:local="clr-namespace:EleCho.MdViewer.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="30"
d:DesignWidth="160"
mc:Ignorable="d">
<DockPanel Margin="5">
<local:SelectableTextBlock
VerticalAlignment="Center"
Text="{Binding Text}"
TextWrapping="Wrap" />
<Button
x:Name="Copy"
Height="20"
Padding="4,0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Background="#AAFFFFFF"
BorderThickness="1"
Click="Copy_Click"
Content="复制"
DockPanel.Dock="Right"
Opacity="1">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Value="True">
<Setter Property="Opacity" Value="0.8"/>
<Setter Property="Opacity" Value="0.8" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</DockPanel>
</UserControl>

View File

@ -470,7 +470,7 @@ public class MarkdownWpfRenderer
}
return codeElement;
return codeElement;
}
public FrameworkElement RenderCodeBlock(CodeBlock codeBlock, CancellationToken cancellationToken)

View File

@ -15,43 +15,26 @@ class PromptUtil
<current_time>
{DateTime.Now}
</current_time>
<current_time>{DateTime.Now}</current_time>
excel文件列信息为
<excel_columns>
{excelPrompt}
</excel_columns>
<excel_columns>{excelPrompt}</excel_columns>
<question>
{msg}
</question>
<question>{msg}</question>
1.
2.
3. 12Excel公式
4.
5. 使
6. 使
```Excel_{{}}
=SUM(A1:A100)
=SUM(A1:A100),SUM(A1:A100),SUM(A1:A100),SUM(A1:A100),SUM(A1:A100),SUM(A1:A100),SUM(A1:A100),SUM(A1:A100),SUM(A1:A100),SUM(A1:A100)
```
";
}
}

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows;
using System.Windows.Markup;
namespace ExcelHelper.Converter
{
public class XamlToContentConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string xamlString && !string.IsNullOrEmpty(xamlString))
{
try
{
var xamlObj = XamlReader.Parse(xamlString);
//var content = xamlObj as UIElement; // Change XamlReader to System.Windows.Markup.XamlReader
return xamlObj;
}
catch (Exception)
{
// Handle parsing exceptions if necessary
}
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -20,7 +20,6 @@
x:Key="BoolToColorConverter"
AIMessageColor="#ECECEC"
UserMessageColor="#DCF8C6" />
<!-- 将布尔值转换为对齐方式 (用户消息靠右AI消息靠左) -->
<local1:BoolToAlignmentConverter
x:Key="BoolToAlignmentConverter"
@ -34,7 +33,7 @@
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<!-- 字符串空判断转换器 -->
<local1:StringEmptyToBoolConverter x:Key="StringEmptyToBoolConverter" />
<local1:XamlToContentConverter x:Key="XamlToContentConverter" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
@ -70,12 +69,20 @@
Background="Transparent"
BorderThickness="0"
Visibility="{Binding Content, Converter={StaticResource StringEmptyToBoolConverter}, ConverterParameter=invert}">
<TabItem Background="Transparent" Header="文档">
<md:MarkdownViewer
x:Name="MdViewer"
Margin="10"
Padding="10"
Content="{Binding Content}" />
<TabItem.Resources>
<Style TargetType="FlowDocumentScrollViewer">
<Setter Property="IsToolBarVisible" Value="False" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Zoom" Value="0.6" />
</Style>
</TabItem.Resources>
<FlowDocumentScrollViewer
Width="Auto"
MinWidth="0"
Document="{Binding FlowDocument}"
VerticalScrollBarVisibility="Visible" />
</TabItem>
<TabItem Background="Transparent" Header="文本">
<TextBox
@ -84,18 +91,51 @@
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
Text="{Binding Content}" />
Text="{Binding Content}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</TabItem>
<TabItem Background="Transparent" Header="XAML">
<TextBox
Margin="5"
Padding="5"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
Text="{Binding ContentXaml}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</TabItem>
</TabControl>
<DockPanel>
<hc:ButtonGroup Margin="5,0">
<hc:ButtonGroup Margin="5">
<Button
Height="20"
hc:IconElement.Geometry="{StaticResource WindowRestoreGeometry}"
Background="Transparent"
FontSize="10"
Foreground="#99000000" />
Foreground="#99000000"
ToolTip="复制所有内容" />
<Button
Height="20"
hc:IconElement.Geometry="{StaticResource RotateRightGeometry}"
hc:IconElement.Height="12"
Background="Transparent"
FontSize="10"
FontWeight="Bold"
Foreground="#99000000"
ToolTip="重新生成" />
<Button
Height="20"
hc:IconElement.Geometry="{StaticResource SaveGeometry}"
hc:IconElement.Height="12"
Background="Transparent"
FontSize="10"
FontWeight="Bold"
Foreground="#99000000"
ToolTip="保存到文件" />
</hc:ButtonGroup>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<TextBlock
@ -150,8 +190,8 @@
<DockPanel>
<hc:ComboBox Height="30" SelectedIndex="1">
<ComboBoxItem Content="DeepSeek-V3" />
<ComboBoxItem Content="DeepSeek-V3" />
<ComboBoxItem Content="DeepSeek-V3" />
<ComboBoxItem Content="DeepSeek-R1" />
<ComboBoxItem Content="豆包-1.5-Pro" />
</hc:ComboBox>
<Button
Height="30"

View File

@ -68,7 +68,7 @@ public partial class AiMessageControll : UserControl
public AiMessageControll()
{
InitializeComponent();
//DataContext = this;
//DataContext = this;
WeakReferenceMessenger.Default.Register<ScrollToEndMessage>("MessageListScrollToEnd", (o, s) => {
Dispatcher.BeginInvoke(() =>

View File

@ -21,7 +21,8 @@ public class ChatMessage : INotifyPropertyChanged
{
_content = value;
OnPropertyChanged(nameof(Content));
//OnPropertyChanged(nameof(FlowDocument));
OnPropertyChanged(nameof(FlowDocument));
OnPropertyChanged(nameof(ContentXaml));
}
}
public FlowDocument FlowDocument
@ -31,6 +32,7 @@ public class ChatMessage : INotifyPropertyChanged
var doc = MarkdownXaml.ToFlowDocument(Content,
new MarkdownPipelineBuilder()
.UseXamlSupportedExtensions()
.UseAdvancedExtensions()
.Build()
);
return doc;
@ -38,6 +40,18 @@ public class ChatMessage : INotifyPropertyChanged
set => OnPropertyChanged(nameof(FlowDocument));
}
public string ContentXaml
{
get
{
var xaml = MarkdownXaml.ToXaml(Content, new MarkdownPipelineBuilder().UseXamlSupportedExtensions().UseAdvancedExtensions().Build());
return xaml;
}
set => OnPropertyChanged(nameof(ContentXaml));
}
private bool _isUser;
public bool IsUser
{

View File

@ -323,7 +323,7 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
Messages.Add(aiChat);
var promptedMsg = PromptUtil.UsePrompt(message,ExcelPromptString);
#if DEBUG
var results = promptedMsg.Split('\n');
var results = TEST_AI_CONTENT.Split('\n');
foreach(var result in results)
{
aiChat.Content += result;
@ -348,15 +348,191 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
private static string TEST_AI_CONTENT = @"
```Excel_H
1231231122222222222222222222
123
1
23
12
3
12
# Welcome to Leanote! Leanote!
## 1.
**** **
~~~~
:
> Leanote官方的话, Leanote, ...
:
1. Vim
2. Emacs
:
- 1
- 2
## 2.
:
![leanote](http://leanote.com/images/logo/leanote_icon_blue.png)
:
[这是去往Leanote官方博客的链接](http://leanote.leanote.com)
## 3.
, 5
```
# h1
## h2
### h3
#### h4
##### h4
###### h5
```
## 4.
:
function get(key) {
return m[key];
}
:
``` javascript
/**
* nth element in the fibonacci series.
* @param n >= 0
* @return the nth element, >= 0.
*/
function fib(n) {
var a = 1, b = 1;
var tmp;
while (--n >= 0) {
tmp = a;
a += b;
b = tmp;
}
return a;
}
document.write(fib(10));
```
```python
class Employee:
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
```
# 5. Markdown
Markdown :
*
*
* Html
*
*
*
* MathJax
## 5.1
Item | Value
-------- | ---
Computer | \$1600
Phone | \$12
Pipe | \$1
, Item列左对齐, Value列右对齐, Qty列居中对齐
| Item | Value | Qty |
| :------- | ----: | :---: |
| Computer | \$1600 | 5 |
| Phone | \$12 | 12 |
| Pipe | \$1 | 234 |
## 5.2
1
: 1
2
:
## 5.4
Leanote[^footnote]
[^footnote]: Leanote是一款强大的开源云笔记产品.
## 5.5
`[TOC]` , :
[TOC]
## 5.6
```sequence
Alice->Bob: Hello Bob, how are you?
Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks!
```
:
```flow
st=>start: Start
e=>end
op=>operation: My Operation
cond=>condition: Yes or No?
st->op->cond
cond(yes)->e
cond(no)->op
```
> **:** :
> - [](http://bramp.github.io/js-sequence-diagrams/)
> - [](http://adrai.github.io/flowchart.js)
## 5.7 MathJax
$
$E=mc^2$
$$
$$\sum_{i=1}^n a_i=0$$
$$f(x_1,x_x,\ldots,x_n) = x_1^2 + x_2^2 + \cdots + x_n^2 $$
$$\sum^{j-1}_{k=0}{\widehat{\gamma}_{kj} z_k}$$
:
$$
\begin{eqnarray}
\vec\nabla \times (\vec\nabla f) & = & 0 \cdots\cdots梯度场必是无旋场\\
\vec\nabla \cdot(\vec\nabla \times \vec F) & = & 0\cdots\cdots旋度场必是无散场\\
\vec\nabla \cdot (\vec\nabla f) & = & {\vec\nabla}^2f\\
\vec\nabla \times(\vec\nabla \times \vec F) & = & \vec\nabla(\vec\nabla \cdot \vec F) - {\vec\nabla}^2 \vec F\\
\end{eqnarray}
$$
访 [MathJax](http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference) 参考更多使用方法。
";
#region Props
[ObservableProperty]