添加项目文件。

This commit is contained in:
ShrlAlgo
2025-09-16 16:06:41 +08:00
parent 0e7807b826
commit 98c65ceb3d
922 changed files with 1009489 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace Szmedi.RvKits.RvScript
{
class ActiveDocumentConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is DocumentViewModel)
return value;
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is DocumentViewModel)
return value;
return Binding.DoNothing;
}
}
}

View File

@@ -0,0 +1,232 @@
<UserControl x:Class="Szmedi.RvKits.RvScript.ChatDialogue"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:AduSkin="https://github.com/aduskin"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:converters="clr-namespace:Szmedi.RvKits.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Szmedi.RvKits.RvScript"
xmlns:markdig="clr-namespace:Markdig.Wpf;assembly=Markdig.Wpf"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:providers="clr-namespace:LangChain.Providers;assembly=LangChain.Providers.Abstractions"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:ChatDialogueViewModel}"
d:Height="500"
d:Width="500">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Szmedi.RvKits;component/WPFUI.xaml" />
<ResourceDictionary Source="pack://application:,,,/Szmedi.RvKits;component/RvScript/MarkdownStyleRes.xaml" />
</ResourceDictionary.MergedDictionaries>
<DrawingImage x:Key="deepseek">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V1024 H1024 V0 H0 Z">
<GeometryDrawing Brush="#FF4D6BFE" Geometry="F1 M1024,1024z M0,0z M979.968,219.0336C969.8816,214.016 965.376,223.5392 959.3856,228.352 957.44,230.0416 955.5968,231.936 953.9072,233.8304 939.0592,249.856 921.856,260.1472 899.1232,258.9184 866.2016,257.024 837.9904,267.52 813.1072,292.864 807.8848,261.5808 790.1696,242.944 763.4432,230.9632 749.312,224.768 735.232,218.5216 725.4528,204.9024 718.4896,195.3792 716.5952,184.6272 713.216,174.08 711.1168,167.6288 708.9664,161.1776 701.5424,160 693.6576,158.8224 690.5344,165.4784 687.4112,171.008 675.0208,193.6896 670.208,219.0336 670.5152,244.3776 671.6416,301.4656 695.808,347.0848 743.8336,379.5968 749.312,383.4368 750.7456,387.0208 749.1072,392.4992 745.728,403.7632 741.9392,414.5152 738.56,425.728 736.4096,432.896 733.0816,434.5856 725.4016,431.4624A217.344,217.344,0,0,1,656.128,384.3584C621.9776,351.3856,591.104,314.8288,552.704,286.4128A511.0784,511.0784,0,0,0,525.1584,267.52C485.9904,229.2736 530.432,197.9904 540.7232,194.1504 551.4752,190.3616 544.512,176.9472 509.6448,177.2032 474.9824,177.2032 443.1872,188.928 402.5856,204.4416 396.5952,206.848 390.4,208.5376 384.1536,209.92A385.9968,385.9968,0,0,0,269.2608,205.8752C194.2016,214.2208 134.2464,249.856 90.0608,310.528 37.1712,383.488 24.4736,466.3296 39.7824,552.8576 55.808,643.8912 102.144,719.4112 173.6192,778.1888 247.5008,839.3728 332.8,869.2736 430.08,863.5392 489.1136,860.16 554.8032,852.2752 628.8896,789.4528 647.5264,798.7712 667.136,802.3552 699.8528,805.2224 724.9408,807.5776 749.1072,803.9936 767.744,800.2048 797.1328,793.9584 794.9824,766.976 784.4352,761.7024 698.6752,721.7664 717.568,738.048 700.3136,724.8896 744.0896,673.28 809.7792,619.52 835.328,445.5424 837.2736,431.7184 835.584,423.1168 835.328,411.8528 835.328,405.1968 836.7616,402.3296 844.4416,401.6128 865.9456,399.4624 886.9376,393.0112 906.0864,382.6688 961.792,352.3584 984.0128,302.4384 989.4912,242.432 990.208,233.3696 989.4912,223.7952 979.712,219.0336L979.9168,219.0336z M495.2576,757.9136C412.1088,692.3776 371.712,670.8736 354.9696,671.8976 339.456,672.8192 342.0672,690.4832 345.6512,702.208 349.2352,713.6768 354.048,721.5616 360.4992,731.5968 365.0048,738.2528 368.128,748.3392 355.8912,755.7632 329.1648,772.4544 282.5728,750.2336 280.4224,749.056 226.1504,717.0048 180.7872,674.9696 148.992,617.1136A401.7152,401.7152,0,0,1,97.3824,438.4256C96.6656,422.8608,101.1712,417.5872,116.2752,414.72A193.024,193.024,0,0,1,177.2032,413.0816C262.0416,425.472 334.3872,463.4624 394.9056,523.6736 429.5168,558.1312 455.5776,598.9376 482.6112,639.1296 511.2832,681.6256 542.1056,722.0736 581.2736,755.2512 595.0976,766.976 606.1568,775.8336 616.6016,782.2848 584.6016,785.8688 531.3536,786.5856 495.0016,757.6576L495.2576,757.9136z M535.1936,500.992A12.288,12.288,0,0,1,547.328,488.8064C554.0352,488.8064,559.5136,494.336,559.5136,500.992A12.288,12.288,0,0,1,547.1232,513.1776A12.032,12.032,0,0,1,534.9376,501.248L534.9376,500.992 535.1424,500.992z M658.944,564.7872A79.872,79.872,0,0,1,635.5456,571.2384A51.8656,51.8656,0,0,1,603.7504,561.2032C592.9984,552.1408,585.1136,546.8672,581.7344,530.8928A64.1024,64.1024,0,0,1,582.4512,507.4432C585.3184,494.336 582.2464,486.1952 572.928,478.5152 565.504,472.3712 555.9296,470.6304 545.4336,470.6304A18.432,18.432,0,0,1,535.3984,467.5584A10.24,10.24,0,0,1,530.0224,461.4144C529.5616,460.032,529.4592,458.5984,529.5616,457.216A10.3424,10.3424,0,0,1,530.8416,453.2224C532.0704,451.072 537.2928,445.7984 538.5216,444.8256 552.6016,436.736 569.088,439.3472 584.1408,445.5424 598.2208,451.2768 608.7168,461.824 624.0768,476.6208 639.5904,494.5408 642.4576,499.5584 651.3152,513.1776 658.2272,523.7248 664.6784,534.6816 668.9792,547.1232 671.5904,554.8032 668.2624,561.2032 658.944,565.0432L658.944,564.7872z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<local:RoleToDisplayConverter x:Key="RoleToDisplayConverter" />
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<converters:InvertBooleanConverter x:Key="InvertBooleanConverter" />
<converters:InvertBooleanToVisibilityConverter x:Key="InvertBooleanToVisibilityConverter" />
<!-- 定义包含 DataTrigger 的 DataTemplate -->
<DataTemplate x:Key="DynamicTemplate" DataType="{x:Type providers:Message}">
<ContentControl x:Name="ContentControl" Content="{Binding}" />
<DataTemplate.Triggers>
<!-- 当 Role 为 Admin 时,使用 Admin 的模板 -->
<DataTrigger Value="{x:Static providers:MessageRole.Ai}" Binding="{Binding Role}">
<Setter TargetName="ContentControl" Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<materialDesign:Card Margin="5"
HorizontalAlignment="{Binding Path=DataContext.Role,
RelativeSource={RelativeSource Mode=Self},
Converter={StaticResource RoleToDisplayConverter}}"
Background="{Binding Path=DataContext.Role,
Mode=OneTime,
RelativeSource={RelativeSource Mode=Self},
Converter={StaticResource RoleToDisplayConverter}}">
<markdig:MarkdownViewer Margin="5" x:Name="Viewer"
Markdown="{Binding Content,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Pipeline="{Binding DataContext.Pipeline, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
<!--<StackPanel Margin="5" Orientation="Horizontal">
<Image Width="32"
Height="32"
Source="{StaticResource deepseek}"
Visibility="{Binding Path=DataContext.Role,
RelativeSource={RelativeSource Mode=Self},
Converter={StaticResource RoleToDisplayConverter}}" />
<md:MarkdownViewer x:Name="MdViewer" Content="{Binding Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>-->
<!-- <mdxam:MarkdownScrollViewer HorizontalAlignment="Right" Markdown="{Binding Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalScrollBarVisibility="Auto" /> -->
</materialDesign:Card>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<!-- 当 Role 为 User 时,使用 User 的模板 -->
<DataTrigger Value="{x:Static providers:MessageRole.Human}" Binding="{Binding Role}">
<Setter TargetName="ContentControl" Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<materialDesign:Card Margin="5"
HorizontalAlignment="{Binding Path=DataContext.Role,
RelativeSource={RelativeSource Mode=Self},
Converter={StaticResource RoleToDisplayConverter}}"
Background="{Binding Path=DataContext.Role,
Mode=OneTime,
RelativeSource={RelativeSource Mode=Self},
Converter={StaticResource RoleToDisplayConverter}}">
<TextBox MaxWidth="300"
VerticalAlignment="Center"
BorderThickness="0"
Margin="5"
Foreground="WhiteSmoke"
Style="{x:Null}"
Background="Transparent"
BorderBrush="{Binding Path=DataContext.Role,
Mode=OneTime,
RelativeSource={RelativeSource Mode=Self},
Converter={StaticResource RoleToDisplayConverter}}"
FontSize="12"
IsReadOnly="True"
Text="{Binding Content}"
TextWrapping="WrapWithOverflow" />
</materialDesign:Card>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- <Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions> -->
<DockPanel>
<Expander DockPanel.Dock="Top" Header="DeepSeek">
<UniformGrid Rows="1">
<ComboBox x:Name="ModelSelected"
materialDesign:HintAssist.Hint="模型选择"
ToolTip="选择Coder模型主要用于代码生成默认添加提示词&#13;Chat模型用于一般聊天">
<ComboBoxItem Content="DeepSeek-Coder" IsSelected="{Binding IsCoderModel}" />
<ComboBoxItem Content="DeepSeek-Chat" IsSelected="{Binding IsCoderModel, Converter={StaticResource InvertBooleanConverter}}" />
</ComboBox>
<PasswordBox x:Name="APIKey"
materialDesign:HintAssist.Hint="APIKey"
materialDesign:PasswordBoxAssist.Password="{Binding ApiKey, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource MaterialDesignOutlinedPasswordBox}" />
</UniformGrid>
</Expander>
<ScrollViewer x:Name="ChatText"
Grid.Row="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<ItemsControl d:ItemsSource="{d:SampleData ItemCount=5}"
ItemsSource="{Binding ChatHistory,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
ItemTemplate="{StaticResource DynamicTemplate}">
<!-- <ItemsControl.ItemTemplate>
<DataTemplate>
<md:Card Margin="5" HorizontalAlignment="{Binding Path=DataContext.Role, RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource RoleToDisplayConverter}}" Background="{Binding Path=DataContext.Role, Mode=OneTime, RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource RoleToDisplayConverter}}">
<StackPanel Orientation="Horizontal">
<Image
Width="32"
Height="32"
Source="{StaticResource deepseek}"
Visibility="{Binding Path=DataContext.Role, RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource RoleToDisplayConverter}}" />
<markdig:MarkdownViewer x:Name="Viewer" Markdown="{Binding Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
-->
<!-- <mdxam:MarkdownScrollViewer HorizontalAlignment="Right" Markdown="{Binding Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalScrollBarVisibility="Auto" /> -->
<!-- </md:Card>
</DataTemplate>
</ItemsControl.ItemTemplate> -->
</ItemsControl>
</ScrollViewer>
</DockPanel>
<materialDesign:Card Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox Grid.Column="0"
Grid.Row="0"
Grid.ColumnSpan="4"
Margin="5"
Text="{Binding UserInput, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="WrapWithOverflow">
<b:Interaction.Triggers>
<b:KeyTrigger Key="Enter">
<b:InvokeCommandAction Command="{Binding SendCommand}" CommandParameter="{Binding ElementName=ChatText}" />
</b:KeyTrigger>
</b:Interaction.Triggers>
</TextBox>
<Button Grid.Column="1"
Grid.Row="1"
Margin="5"
Command="{Binding NewSessionCommand}"
ToolTip="新对话">
<materialDesign:PackIcon Kind="Dialogue" />
</Button>
<Button Grid.Column="2"
Margin="5"
Grid.Row="1"
Command="{Binding SendCommand}"
CommandParameter="{Binding ElementName=ChatText}"
materialDesign:ButtonProgressAssist.IsIndeterminate="{Binding SendCommand.IsRunning, Mode=OneWay}"
materialDesign:ButtonProgressAssist.IsIndicatorVisible="{Binding SendCommand.IsRunning, Mode=OneWay}"
materialDesign:ButtonProgressAssist.Value="-1"
ToolTip="发送"
Visibility="{Binding SendCommand.IsRunning, Converter={StaticResource InvertBooleanToVisibilityConverter}}">
<materialDesign:PackIcon Kind="Send" />
</Button>
<Button Grid.Column="3"
Margin="5"
Grid.Row="1"
Command="{Binding SendCancelCommand}"
CommandParameter="{Binding ElementName=ChatText}"
ToolTip="取消"
Visibility="{Binding SendCommand.IsRunning, Converter={StaticResource BooleanToVisibilityConverter}}">
<materialDesign:PackIcon Kind="Cancel" />
</Button>
</Grid>
</materialDesign:Card>
<!-- <GroupBox Width="100" Header="分类" />
<StackPanel Grid.Column="1">
<TextBlock Text="A1" />
<TextBlock Text="A23" />
<Button Content="Button" />
<Button Content="Button" />
<Button Content="Button" />
</StackPanel> -->
</Grid>
</UserControl>

View File

@@ -0,0 +1,208 @@
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Szmedi.RvKits.RvScript
{
/// <summary>
/// ChatDialogue.xaml 的交互逻辑
/// </summary>
public partial class ChatDialogue
{
private readonly ChatDialogueViewModel viewModel = new ChatDialogueViewModel();
public ChatDialogue()
{
InitializeComponent();
this.DataContext = viewModel;
}
//_deepSeekClient = new DeepSeekClient("sk-3a3126167f1343228b1a5745bcd0bf01");
///// <summary>
///// DeepSeek对象
///// </summary>
//private DeepSeekClient _deepSeekClient;
///// <summary>
///// 系统角色设定
///// </summary>
//private const string SysContent = "你是 DeepSeek AI 提供的人工智能助手你更擅长中文和英文的对话。你会为用户提供安全有帮助准确的回答。同时你会拒绝一切涉及恐怖主义种族歧视黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言";
///// <summary>
///// 单轮流式聊天
///// </summary>
///// <param name="sender"></param>
///// <param name="e"></param>
//private async void button1_Click(object sender, RoutedEventArgs e)
//{
// try
// {
// richTextBox1.Document.Blocks.Clear();
// //------
// var chatReq = new ChatRequest
// {
// model = ChatModels.DeepseekChat,
// messages = new List<MessagesItem> {
// new MessagesItem { role = ChatRoles.System, content = SysContent },
// new MessagesItem { role = ChatRoles.User, content = textBox1.Text }
// },
// stream = true
// };
// // 订阅事件
// _deepSeekClient.MessageReceivedEventHandler -= OnMessageReceived;
// _deepSeekClient.ErrorEventHandler -= OnErrorMsg;
// _deepSeekClient.MessageReceivedEventHandler += OnMessageReceived;
// _deepSeekClient.ErrorEventHandler += OnErrorMsg;
// // 开始任务
// await _deepSeekClient.ChatStreamAsync(chatReq).ConfigureAwait(true);
// // 订阅SSE 消息事件
// void OnMessageReceived(object s, ChatResponse m)
// {
// //Console.WriteLine("聊天内容:" + ee);
// this.Dispatcher.Invoke(() =>
// {
// var msg = m.choices?.FirstOrDefault()?.delta.content;
// if (msg != null) richTextBox1.AppendText(msg);
// });
// }
// // 订阅SSE 错误事件
// void OnErrorMsg(object s, Exception ex)
// {
// MessageBox.Show(ex.Message);
// }
// }
// catch (Exception ex)
// {
// Console.WriteLine("流式聊天失败:" + ex.Message);
// }
//}
///// <summary>
///// 单轮普通聊天
///// </summary>
///// <param name="sender"></param>
///// <param name="e"></param>
//private async void button2_Click(object sender, RoutedEventArgs e)
//{
// try
// {
// var chatReq = new ChatRequest
// {
// model = ChatModels.DeepseekChat,
// messages = new List<MessagesItem> {
// new MessagesItem { role = ChatRoles.System, content = SysContent },
// new MessagesItem { role = ChatRoles.User, content = textBox1.Text }
// }
// };
// var chatRes = await _deepSeekClient.ChatAsync(chatReq).ConfigureAwait(true);
// Console.WriteLine("聊天内容:" + chatRes.choices?.FirstOrDefault()?.message.content);
// Paragraph paragraph = new Paragraph();
// paragraph.Inlines.Add(new Run(chatRes.choices?.FirstOrDefault()?.message.content));
// richTextBox1.Document.Blocks.Add(paragraph);
// }
// catch (Exception ex)
// {
// Console.WriteLine("聊天失败:" + ex.Message);
// }
//}
///// <summary>
///// 多轮对话列表
///// </summary>
//private List<MessagesItem> HistoryList = new List<MessagesItem> { new MessagesItem { role = ChatRoles.System, content = SysContent } };
///// <summary>
///// 多轮流式对话
///// </summary>
///// <param name="sender"></param>
///// <param name="e"></param>
//private async void button3_Click(object sender, RoutedEventArgs e)
//{
// try
// {
// richTextBox1.Document.Blocks.Clear();
// //------当前要说的内容
// HistoryList.Add(new MessagesItem { role = ChatRoles.User, content = textBox1.Text });
// //------
// var chatReq = new ChatRequest
// {
// model = ChatModels.DeepseekChat,
// messages = HistoryList,
// stream = true
// };
// // 订阅事件
// _deepSeekClient.MessageReceivedEventHandler -= OnMessageReceived;
// _deepSeekClient.ErrorEventHandler -= OnErrorMsg;
// _deepSeekClient.CloseedEventHandler -= OnCloseed;
// _deepSeekClient.MessageReceivedEventHandler += OnMessageReceived;
// _deepSeekClient.ErrorEventHandler += OnErrorMsg;
// _deepSeekClient.CloseedEventHandler += OnCloseed;
// // 开始任务
// await _deepSeekClient.ChatStreamAsync(chatReq).ConfigureAwait(true);
// // 局部函数,订阅SSE 消息事件
// void OnMessageReceived(object s, ChatResponse m)
// {
// //Console.WriteLine("聊天内容:" + ee);
// this.Dispatcher
// .Invoke(
// () =>
// {
// var msg = m.choices?.FirstOrDefault()?.delta.content;
// if (msg != null)
// {
// richTextBox1.AppendText(msg);
// }
// });
// }
// // 局部函数,订阅SSE 错误事件
// void OnErrorMsg(object s, Exception ex)
// {
// MessageBox.Show(ex.Message);
// }
// // 局部函数,订阅SSE 关闭事件
// void OnCloseed(object s, string ex)
// {
// HistoryList.Add(new MessagesItem { role = ChatRoles.Assistant, content = textBox1.Text });
// }
// }
// catch (Exception ex)
// {
// Console.WriteLine("流式聊天失败:" + ex.Message);
// }
//}
///// <summary>
///// 多轮普通聊天
///// </summary>
///// <param name="sender"></param>
///// <param name="e"></param>
//private async void button4_Click(object sender, RoutedEventArgs e)
//{
// try
// {
// //------当前要说的内容
// HistoryList.Add(new MessagesItem { role = ChatRoles.User, content = textBox1.Text });
// //-------------------
// var chatReq = new ChatRequest
// {
// model = ChatModels.DeepseekChat,
// messages = HistoryList
// };
// var chatRes = await _deepSeekClient.ChatAsync(chatReq).ConfigureAwait(true);
// HistoryList.Add(new MessagesItem { role = ChatRoles.Assistant, content = textBox1.Text });
// Console.WriteLine("聊天内容:" + chatRes.choices?.FirstOrDefault()?.message.content);
// Paragraph paragraph = new Paragraph();
// paragraph.Inlines.Add(new Run(chatRes.choices?.FirstOrDefault()?.message.content));
// richTextBox1.Document.Blocks.Add(paragraph);
// }
// catch (Exception ex)
// {
// Console.WriteLine("聊天失败:" + ex.Message);
// }
//}
}
}

View File

@@ -0,0 +1,321 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
//using LangChain.Chains.LLM;
//using LangChain.Memory;
//using LangChain.Prompts;
using LangChain.Providers;
using LangChain.Providers.DeepSeek;
using LangChain.Providers.DeepSeek.Predefined;
using LangChain.Providers.OpenAI.Predefined;
using Markdig;
using Markdig.Syntax;
using Markdig.Wpf.ColorCode;
using tryAGI.OpenAI;
//using LangChain.Schema;
//using static LangChain.Chains.Chain;
namespace Szmedi.RvKits.RvScript;
public partial class ChatDialogueViewModel : ObservableObject
{
public DeepSeekConfiguration Configuration { get; set; } = new DeepSeekConfiguration()
{
Endpoint = "https://api.deepseek.com",
ChatSettings = new() { UseStreaming = true },
};
private ScrollViewer scrollViewer;
/// <summary>
/// 当前AI的回复
/// </summary>
[ObservableProperty]
private Message? currentRespone = Message.Ai(string.Empty);
[ObservableProperty]
private bool isCoderModel = true;
partial void OnIsCoderModelChanged(bool value)
{
NewSession();
}
[ObservableProperty]
private string apiKey = Properties.Settings.Default.APIKey;
partial void OnApiKeyChanged(string oldValue, string newValue)
{
if (!string.IsNullOrEmpty(newValue) && !string.IsNullOrWhiteSpace(newValue) && newValue.StartsWith("sk-"))
{
Properties.Settings.Default.APIKey = newValue;
Properties.Settings.Default.Save();
}
}
/// <summary>
/// 发送给AI的消息包括上下文记录
/// </summary>
private Message? CurrentRequest { get; set; } = Message.Empty;
public ChatDialogueViewModel()
{
ChatHistory ??= new ObservableCollection<Message?>();
}
/// <summary>
/// 用户输入
/// </summary>
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(SendCommand))]
private string userInput;
private bool CanSend()
{
return !string.IsNullOrEmpty(UserInput);
}
public MarkdownPipeline Pipeline { get; set; } = new MarkdownPipelineBuilder().UseAdvancedExtensions().UseColorCodeWpf().Build();
/// <summary>
/// 历史聊天记录
/// </summary>
public ObservableCollection<Message?> ChatHistory { get; set; }
[RelayCommand(CanExecute = nameof(CanSend), IncludeCancelCommand = true)]
private async Task SendAsync(object obj, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(Configuration.ApiKey) || string.IsNullOrEmpty(ApiKey))
{
Configuration.ApiKey = "sk-3a3126167f1343228b1a5745bcd0bf01";
}
else
{
Configuration.ApiKey = Properties.Settings.Default.APIKey;
}
if (string.IsNullOrEmpty(Configuration.ApiKey))
{
var result = MessageBox.Show("请先设置APIKey若无APIKey前往DeepSeek官网获取", "提示", MessageBoxButton.YesNo, MessageBoxImage.Information);
if (result == MessageBoxResult.Yes)
{
Process.Start("https://platform.deepseek.com/");
}
return;
}
try
{
if (obj is not ScrollViewer scroll)
{
return;
}
scrollViewer = scroll;
//UserInput.Content=string.Empty;
#region Full
// //var llm = new OpenAiLatestFastChatModel(provider);
// var deepseekLLM = new DeepSeekChatModel(new DeepSeekProvider(config));
// //var embeddingModel = new TextEmbeddingV3SmallModel(provider);
// var prompt = new PromptTemplate(new PromptTemplateInput(
//template: "Revit二次开发中使用变量doc和uidoc两个变量构造一个保证可以执行的C#代码块添加相应注释不需要方法签名和using命名空间但使用时需要完整的命名空间。实现{需求}的功能", inputVariables: ["需求"]));
// var chain = new LlmChain(new LlmChainInput(deepseekLLM, prompt));
// var result = await chain.CallAsync(new ChainValues(new Dictionary<string, object>
// {
// { "需求", UserInput}
// })).ConfigureAwait(true);
// // The result is an object with a `text` property.
// Respones = result.Value["text"].ToString();
#endregion
if (IsCoderModel)
{
if (ChatHistory.Count == 0)
{
CurrentRequest += Message.Human($"你是一个专业的Revit二次开发工程师不会随意捏造事实能客观地回答用户的问题对于不确定或难以理解的问题需要用户补充说明的需要主动提出。你需要在{GlobalVariables.UIApplication.Application.VersionName}二次开发中使用已定义的uidoc、doc两个变量构造一个正确执行的C#代码块保证使用的RevitAPI的所有方法都能在{GlobalVariables.UIApplication.Application.VersionName}的API文档中找到在代码中添加关键的注释不需要方法签名和using命名空间但使用类名时需要完整的命名空间。需求是{UserInput}");
ChatHistory.Add(CurrentRequest);
}
else
{
ChatHistory.Add(Message.Human(UserInput));
CurrentRequest += Message.Human(UserInput);
}
UserInput = string.Empty;
var DeepseekCoder = new DeepSeekCoderModel(new DeepSeekProvider(Configuration));
DeepseekCoder.ResponseReceived += DeepseekLLM_ResponseReceived;
DeepseekCoder.DeltaReceived += DeepseekLLM_DeltaReceived;
DeepseekCoder.RequestSent += DeepseekLLM_RequestSent;
/*var result = */
await DeepseekCoder.GenerateAsync(CurrentRequest, cancellationToken: cancellationToken);
}
else
{
ChatHistory.Add(Message.Human(UserInput));
DeepSeekChatModel DeepseekLLM = new DeepSeekChatModel(new DeepSeekProvider(Configuration));
DeepseekLLM.ResponseReceived += DeepseekLLM_ResponseReceived;
DeepseekLLM.DeltaReceived += DeepseekLLM_DeltaReceived;
DeepseekLLM.RequestSent += DeepseekLLM_RequestSent;
CurrentRequest += Message.Human(UserInput);
UserInput = string.Empty;
/*var result = */
await DeepseekLLM.GenerateAsync(CurrentRequest, cancellationToken: cancellationToken);
}
// Since the LLMChain is a single-input, single-output chain, we can also call it with `run`.
// This takes in a string and returns the `text` property.
//var result2 = await chain.RunAsync("彩色长筒靴");
//Console.WriteLine(result2);
// var chatPrompt = ChatPromptTemplate.FromPromptMessages([
// SystemMessagePromptTemplate.FromTemplate(
// "You are a helpful assistant that translates {input_language} to {output_language}."),
// HumanMessagePromptTemplate.FromTemplate("{text}")
// ]);
// var chainB = new LlmChain(new LlmChainInput(deepseekLLM, chatPrompt)
// {
// Verbose = true
// });
// var resultB = await chainB.CallAsync(new ChainValues(new Dictionary<string, object>(3)
//{
// {"input_language", "English"},
// {"output_language", "French"},
// {"text", "I love programming"},
//}));
// Console.WriteLine(resultB.Value["text"]);
}
catch (OperationCanceledException)
{
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void DeepseekLLM_RequestSent(object sender, ChatRequest e)
{
Debug.WriteLine("-------------RequestSent-------------");
//Debug.WriteLine($"发送者{sender}");
//scrollViewer.Dispatcher.Invoke(() =>
//{
// ChatHistory.Add(CurrentRespone);
//});
}
//接收完毕
private void DeepseekLLM_ResponseReceived(object sender, ChatResponse e)
{
Debug.WriteLine("-------------ResponseReceived-------------");
scrollViewer.Dispatcher.Invoke(() =>
{
//Debug.WriteLine($"发送者:{sender};使用量:{e.Usage}");
CurrentRequest += e.LastMessage;
var code = GetCode(e.LastMessage.ToString());
if (!string.IsNullOrEmpty(code))
{
WeakReferenceMessenger.Default.Send(code, "RunScript");
}
CurrentRespone = Message.Ai(string.Empty);
Debug.WriteLine($"当前回复:{CurrentRespone}");
//最后一条完整的消息
//Debug.WriteLine($"{ChatHistory}");
//ChatHistory.Add(e.LastMessage);
//Respones.Content += e.Content;
});
}
private string GetCode(string markdownText)
{
//var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
//var RenderedMarkdown = Markdown.ToPlainText(markdownText, pipeline);
// 提取代码块(假设是 C# 代码)
var match = Regex.Match(markdownText, @"```csharp\s([\s\S]*?)\s```", RegexOptions.Multiline);
if (match.Success)
{
return match.Groups[1].Value;
}
return string.Empty;
//if (match.Success)
//{
// WeakReferenceMessenger.Default.Send(match.Groups[1].Value.Trim(), "RunScript");
//}
}
//partial void OnCurrentResponeChanged(Message? value)
//{
//}
//接收Delta
private void DeepseekLLM_DeltaReceived(object sender, ChatResponseDelta e)
{
Debug.WriteLine("-------------DeltaReceived-------------");
if (string.IsNullOrEmpty(e.Content))
{
return;
}
scrollViewer.Dispatcher.Invoke(() =>
{
if (ChatHistory.Contains(CurrentRespone))
{
Debug.WriteLine($"包含CurrentRespone对象");
ChatHistory.Remove(CurrentRespone);
}
Debug.WriteLine($"当前回复块:{e.Content}");
CurrentRespone += Message.Ai(e.Content);
if (!ChatHistory.Contains(CurrentRespone))
{
ChatHistory.Add(CurrentRespone);
}
//判断滚动条是否在底部
if (scrollViewer.VerticalOffset == scrollViewer.ExtentHeight - scrollViewer.ViewportHeight)
{
scrollViewer?.ScrollToEnd();
}
//ChatHistory.
//Respones.Content += e.Content;
});
}
[RelayCommand]
private void NewSession()
{
ChatHistory?.Clear();
CurrentRequest = Message.Empty;
CurrentRespone = Message.Ai(string.Empty);
}
//[RelayCommand]
//private void SendCode()
//{
// ChatHistory?.Clear();
// CurrentRequest = Message.Empty;
//}
}

View File

@@ -0,0 +1,28 @@
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
using Microsoft.CodeAnalysis.CodeActions;
using RoslynPad.Roslyn.CodeActions;
namespace Szmedi.RvKits.RvScript
{
internal sealed class CodeActionsConverter : MarkupExtension, IValueConverter
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((CodeAction)value).GetCodeActions();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

View File

@@ -0,0 +1,100 @@
using System.Text;
using System.Windows;
using System.Windows.Documents;
using ColorCode;
using ColorCode.Styling;
using ColorCode.Wpf;
using Markdig.Parsers;
using Markdig.Renderers;
using Markdig.Renderers.Wpf;
using Markdig.Syntax;
#nullable enable
namespace Markdig.Wpf.ColorCode;
public class ColorCodeBlockRenderer : WpfObjectRenderer<CodeBlock>
{
private readonly CodeBlockRenderer _underlyingCodeBlockRenderer;
private readonly StyleDictionary _styleDictionary;
/// <summary>
/// Create a new <see cref="ColorCodeBlockRenderer"/> with the specified <paramref name="underlyingCodeBlockRenderer"/> and <paramref name="styleDictionary"/>.
/// </summary>
/// <param name="underlyingCodeBlockRenderer">The underlying CodeBlockRenderer to handle unsupported languages.</param>
/// <param name="styleDictionary">A StyleDictionary for custom styling.</param>
public ColorCodeBlockRenderer(CodeBlockRenderer underlyingCodeBlockRenderer, StyleDictionary styleDictionary)
{
_underlyingCodeBlockRenderer = underlyingCodeBlockRenderer;
_styleDictionary = styleDictionary;
}
/// <summary>
/// Writes the specified <paramref name="codeBlock"/> to the <paramref name="renderer"/>.
/// </summary>
/// <param name="renderer">The renderer.</param>
/// <param name="codeBlock">The code block to render.</param>
protected override void Write(WpfRenderer renderer, CodeBlock codeBlock)
{
if (codeBlock is not FencedCodeBlock fencedCodeBlock ||
codeBlock.Parser is not FencedCodeBlockParser fencedCodeBlockParser)
{
_underlyingCodeBlockRenderer.Write(renderer, codeBlock);
return;
}
var language = ExtractLanguage(fencedCodeBlock, fencedCodeBlockParser);
if (language is null)
{
_underlyingCodeBlockRenderer.Write(renderer, codeBlock);
return;
}
var code = ExtractCode(codeBlock);
var formatter = new RichTextBoxFormatter(_styleDictionary);
var paragraph = new Paragraph();
paragraph.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.CodeBlockStyleKey);
formatter.FormatInlines(code, language, paragraph.Inlines);
renderer.WriteBlock(paragraph);
}
private static ILanguage? ExtractLanguage(IFencedBlock fencedCodeBlock, FencedCodeBlockParser parser)
{
var languageId = fencedCodeBlock.Info!.Replace(parser.InfoPrefix!, string.Empty);
return string.IsNullOrWhiteSpace(languageId) ? null : Languages.FindById(languageId);
}
private static string ExtractCode(LeafBlock leafBlock)
{
var code = new StringBuilder();
var lines = leafBlock.Lines.Lines;
//var totalLines = lines.Length;
var totalLines = lines == null ? 0 : lines.Length;
for (var index = 0; index < totalLines; index++)
{
var line = lines[index];
var slice = line.Slice;
if (slice.Text == null)
{
continue;
}
var lineText = slice.Text.Substring(slice.Start, slice.Length);
if (index > 0)
{
code.AppendLine();
}
code.Append(lineText);
}
return code.ToString();
}
}

View File

@@ -0,0 +1,55 @@
using ColorCode.Styling;
using Markdig.Renderers;
using Markdig.Renderers.Wpf;
namespace Markdig.Wpf.ColorCode;
public class ColorCodeWpfExtension : IMarkdownExtension
{
private readonly StyleDictionary _styleDictionary;
/// <summary>
/// Creates a new <see cref="ColorCodeWpfExtension"/> with the specified <paramref name="styleDictionary"/>.
/// </summary>
/// <param name="styleDictionary">A dictionary indicating how to style the code.</param>
public ColorCodeWpfExtension(StyleDictionary styleDictionary) => _styleDictionary = styleDictionary;
/// <summary>
/// Sets up this extension for the specified pipeline.
/// </summary>
/// <param name="pipeline">The pipeline.</param>
public void Setup(MarkdownPipelineBuilder pipeline)
{
}
/// <summary>
/// Sets up this extension for the specified renderer.
/// </summary>
/// <param name="pipeline">The pipeline used to parse the document.</param>
/// <param name="renderer">The renderer.</param>
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
if (renderer is not WpfRenderer wpfRenderer)
{
return;
}
var codeBlockRenderer = wpfRenderer.ObjectRenderers.FindExact<CodeBlockRenderer>();
if (codeBlockRenderer != null)
{
wpfRenderer.ObjectRenderers.Remove(codeBlockRenderer);
}
else
{
codeBlockRenderer = new CodeBlockRenderer();
}
wpfRenderer.ObjectRenderers.AddIfNotAlready(
new ColorCodeBlockRenderer(
codeBlockRenderer,
_styleDictionary
)
);
}
}

View File

@@ -0,0 +1,18 @@
using System.Windows;
using System.Windows.Controls;
namespace Szmedi.RvKits.RvScript
{
public class DocumentTemplateSelector : DataTemplateSelector
{
public DataTemplate DocumentViewTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is DocumentViewModel)
return DocumentViewTemplate;
return base.SelectTemplate(item, container);
}
}
}

View File

@@ -0,0 +1,265 @@
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Utils;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Text;
using TextDocument = ICSharpCode.AvalonEdit.Document.TextDocument;
namespace Szmedi.RvKits.RvScript
{
/// <summary>
/// 每个脚本文件视图的ViewModel
/// </summary>
public partial class DocumentViewModel : ObservableObject /*ObservableRecipient, IRecipient<string>*/
{
[ObservableProperty]
private bool _isReadOnly;
RoslynEditorViewModel RoslynEditorViewModel { get; }
public DocumentViewModel(RoslynEditorViewModel roslynEditorViewModel, string FilePath)
{
RoslynEditorViewModel = roslynEditorViewModel;
this.FilePath = FilePath;
Title = FileName;
}
// ...
public DocumentViewModel(RoslynEditorViewModel roslynEditorViewModel)
{
//WeakReferenceMessenger.Default.Register<DocumentViewModel, string, string>(this, "RunScript", (r, m) => r.Receive(m));
RoslynEditorViewModel = roslynEditorViewModel;
IsDirty = true;
Title = FileName;
}
internal void Initialize(DocumentId id)
{
Id = id;
if (Document != null && Document.TextLength > 0)
{
var doc = RoslynEditorViewModel.Host.GetDocument(id);
if (doc != null)
{
RoslynEditorViewModel.Host.UpdateDocument(doc.WithText(SourceText.From(Document.Text)));
IsDirty = false;
}
}
}
internal void OnTextChanged(object sender, EventArgs e)
{
IsDirty = true;
}
public DocumentId Id { get; private set; }
[ObservableProperty]
private TextDocument _document = null;
[ObservableProperty]
private string title = null;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FileName))]
[NotifyPropertyChangedFor(nameof(Title))]
private bool isDirty = false;
private string _isReadOnlyReason = string.Empty;
public string IsReadOnlyReason
{
get
{
return _isReadOnlyReason;
}
protected set
{
SetProperty(ref _isReadOnlyReason, value);
}
}
private string _filePath = null;
public string FilePath
{
get { return _filePath; }
set
{
if (_filePath != value)
{
_filePath = value;
OnPropertyChanged(nameof(FilePath));
OnPropertyChanged(nameof(FileName));
OnPropertyChanged(nameof(Title));
if (File.Exists(_filePath))
{
Document = new TextDocument();
IsDirty = false;
IsReadOnly = false;
// Check file attributes and set to read-only if file attributes indicate that
if ((File.GetAttributes(_filePath) & FileAttributes.ReadOnly) != 0)
{
IsReadOnly = true;
IsReadOnlyReason = "无法编辑该文件,另一个进程正在写入\n" +
"如果你想编辑它,请修改访问许可或另存文件到其他位置。";
}
using (FileStream fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (StreamReader reader = FileReader.OpenStream(fs, System.Text.Encoding.UTF8))
{
Document = new TextDocument(reader.ReadToEnd());
}
}
ContentId = _filePath;
}
}
}
}
public string FileName
{
get
{
if (FilePath == null)
return "未命名脚本" + (IsDirty ? "*" : "");
return Path.GetFileName(FilePath) + (IsDirty ? "*" : "");
}
}
[ObservableProperty]
private string _contentId = null;
[ObservableProperty]
private bool _isActive = false;
[ObservableProperty]
private bool _isSelected = false;
public string Text { get; set; }
public bool HasError { get; private set; }
//private static MethodInfo HasSubmissionResult { get; } =
// typeof(Compilation).GetMethod(nameof(HasSubmissionResult), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
[RelayCommand(CanExecute = nameof(IsDirty))]
private void Save()
{
Text = GetCode();
RoslynEditorViewModel.Save(this, false);
}
private string GetCode()
{
var document = RoslynEditorViewModel.Host.GetDocument(Id);
if (document == null)
return string.Empty;
return document.GetTextAsync()?.Result.ToString();
}
[RelayCommand(CanExecute = nameof(IsDirty))]
private void SaveAs()
{
Text = GetCode();
RoslynEditorViewModel.Save(this, true);
}
[RelayCommand]
private void Close()
{
RoslynEditorViewModel.Close(this);
}
[RelayCommand]
private void Run()
{
Text = GetCode();
RoslynEditorViewModel.Run(this);
}
[RelayCommand]
private void Format()
{
var document = RoslynEditorViewModel.Host.GetDocument(Id);
var formattedDocument = Formatter.FormatAsync(document).Result;
RoslynEditorViewModel.Host.UpdateDocument(formattedDocument);
}
[RelayCommand]
private void Comment()
{
if (RoslynEditorViewModel.CodeEditor == null)
{
return;
}
var roslynEditor = RoslynEditorViewModel.CodeEditor;
var document = roslynEditor.Document;
var startLine = document.GetLineByOffset(roslynEditor.SelectionStart);
var endLine = document.GetLineByOffset(roslynEditor.SelectionStart + roslynEditor.SelectionLength);
document.BeginUpdate();
var line = startLine;
while (line != null && line.LineNumber <= endLine.LineNumber)
{
var whitespace = TextUtilities.GetLeadingWhitespace(document, line);
if (line.Length > whitespace.Length)
{
var text = document.GetText(whitespace) + "//";
document.Replace(whitespace.Offset, whitespace.Length, text, OffsetChangeMappingType.RemoveAndInsert);
}
line = line.NextLine;
}
document.EndUpdate();
}
[RelayCommand]
private void UnComment()
{
if (RoslynEditorViewModel.CodeEditor == null)
{
return;
}
var roslynEditor = RoslynEditorViewModel.CodeEditor;
var document = roslynEditor.Document;
var startLine = document.GetLineByOffset(roslynEditor.SelectionStart);
var endLine = document.GetLineByOffset(roslynEditor.SelectionStart + roslynEditor.SelectionLength);
document.BeginUpdate();
var line = startLine;
while (line != null && line.LineNumber <= endLine.LineNumber)
{
var whitespace = TextUtilities.GetLeadingWhitespace(document, line);
if (line.Length > whitespace.Length + 2)
{
var text = document.GetText(whitespace.EndOffset, 2);
if (text == "//")
document.Remove(whitespace.EndOffset, 2);
}
line = line.NextLine;
}
document.EndUpdate();
}
//public void Receive(string message)
//{
// this.Text = message;
//}
}
}

View File

@@ -0,0 +1,29 @@
using System.Windows.Media;
namespace ColorCode.Wpf.Common
{
public static class ExtensionMethods
{
public static SolidColorBrush GetSolidColorBrush(this string hex)
{
hex = hex.Replace("#", string.Empty);
byte a = 255;
int index = 0;
if (hex.Length == 8)
{
a = (byte)(Convert.ToUInt32(hex.Substring(index, 2), 16));
index += 2;
}
byte r = (byte)(Convert.ToUInt32(hex.Substring(index, 2), 16));
index += 2;
byte g = (byte)(Convert.ToUInt32(hex.Substring(index, 2), 16));
index += 2;
byte b = (byte)(Convert.ToUInt32(hex.Substring(index, 2), 16));
SolidColorBrush myBrush = new(Color.FromArgb(a, r, g, b));
return myBrush;
}
}
}

View File

@@ -0,0 +1,247 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avCompletion="clr-namespace:ICSharpCode.AvalonEdit.CodeCompletion;assembly=ICSharpCode.AvalonEdit"
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
xmlns:editor="clr-namespace:RoslynPad.Editor;assembly=RoslynPad.Editor.Windows"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Szmedi.RvKits;component/WPFUI.xaml" />
</ResourceDictionary.MergedDictionaries>
<DrawingImage x:Key="FindNext">
<DrawingImage.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
<GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M11.5,5C11.31,5,11.126,5.027,10.943,5.056L12,4 8,0 2,0 4,2 2,2 2,6 4,6 2,8 8,8 8.056,7.943C8.027,8.126 8,8.31 8,8.5 8,8.822 8.046,9.139 8.137,9.449L5.5,12 8,14.5 10.551,11.863C10.861,11.954 11.178,12 11.5,12 13.43,12 15,10.43 15,8.5 15,6.57 13.43,5 11.5,5" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M13,8.5C13,7.672 12.328,7 11.5,7 10.672,7 10,7.672 10,8.5 10,9.328 10.672,10 11.5,10 12.328,10 13,9.328 13,8.5 M14,8.5C14,9.881 12.881,11 11.5,11 11.068,11 10.668,10.881 10.312,10.688L8,13 7,12 9.312,9.688C9.119,9.332 9,8.932 9,8.5 9,7.119 10.119,6 11.5,6 12.881,6 14,7.119 14,8.5" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M5,7L7,5 3,5 3,3 7,3 5,1 7,1 10,4 7,7z" />
<GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M10,8.5C10,9.328 10.672,10 11.5,10 12.328,10 13,9.328 13,8.5 13,7.672 12.328,7 11.5,7 10.672,7 10,7.672 10,8.5" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="FindPrevious">
<DrawingImage.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
<GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M12.5,5C11.961,5,11.457,5.133,11,5.351L11,2 8.414,2 10.414,0 5.586,0 1.586,4 5.586,8 9.051,8C9.027,8.164 9,8.328 9,8.5 9,8.822 9.046,9.139 9.137,9.449L6.5,12 9,14.5 11.551,11.863C11.861,11.954 12.178,12 12.5,12 14.43,12 16,10.43 16,8.5 16,6.57 14.43,5 12.5,5" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M14,8.5C14,7.672 13.328,7 12.5,7 11.672,7 11,7.672 11,8.5 11,9.328 11.672,10 12.5,10 13.328,10 14,9.328 14,8.5 M15,8.5C15,9.881 13.881,11 12.5,11 12.068,11 11.668,10.881 11.312,10.688L9,13 8,12 10.312,9.688C10.119,9.332 10,8.932 10,8.5 10,7.119 11.119,6 12.5,6 13.881,6 15,7.119 15,8.5" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M8,7L6,7 3,4 6,1 8,1 6,3 10,3 10,5 6,5z" />
<GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M11,8.5C11,9.328 11.672,10 12.5,10 13.328,10 14,9.328 14,8.5 14,7.672 13.328,7 12.5,7 11.672,7 11,7.672 11,8.5" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="ReplaceNext">
<DrawingImage.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="#FF424242" Geometry="F1M12,6L10,6 10,4 12,4 12,6z M10,3L10,1 9,1 9,6 9,7 10,7 12,7 13,7 13,4 13,3 10,3z" />
<GeometryDrawing Brush="#FF424242" Geometry="F1M3,10L6,10 6,11 4,11 4,13 6,13 6,14 3,14 3,10z M1,15L8,15 8,9 1,9 1,15z" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M2.97,3.5L3,6 2,5 2,6.5 3.5,8 5,6.5 5,5 4,6 3.97,3.5C3.97,3.22,4.2,3,4.47,3L8,3 8,2 4.47,2C3.65,2,2.97,2.67,2.97,3.5z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="ReplaceAll">
<DrawingImage.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M5,6L5,4 7.156,4C7.143,4.035 7.121,4.065 7.109,4.102 7.037,4.338 7,4.593 7,4.857 7,5.135 7.044,5.4 7.13,5.648 7.173,5.772 7.229,5.889 7.293,6z M15.903,2.917C15.832,2.582 15.717,2.277 15.56,2.008 15.376,1.696 15.134,1.442 14.847,1.26 14.524,1.052 14.148,0.946 13.73,0.946L13.697,0.946 13.697,0 11,0 11,1.365C10.869,1.275 10.729,1.198 10.577,1.138 10.29,1.023 9.961,0.965 9.598,0.965 9.425,0.965 9.247,0.981 9.047,1.016 8.885,1.045 8.728,1.082 8.578,1.126 8.427,1.172 8.289,1.221 8.149,1.28 8.093,1.306 8.047,1.33 8,1.354L8,1 3.479,1C2.1,1,0.979,2.122,0.979,3.509L0.979,3.565 0,2.586 0,6.914 1.086,8 0,8 0,16 12,16 12,14 14,14 14,6.927C14.253,6.88 14.495,6.807 14.707,6.678 15.016,6.492 15.275,6.235 15.478,5.916 15.658,5.635 15.794,5.305 15.882,4.932 15.96,4.597 16,4.236 16,3.861 16,3.54 15.968,3.223 15.903,2.917" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M5,8L12,8 12,13 13,13 13,7 5,7z" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M10.1836,4.3809C10.1836,4.5119 10.1626,4.6329 10.1246,4.7459 10.0866,4.8579 10.0326,4.9569 9.9596,5.0409 9.8876,5.1249 9.8026,5.1919 9.7046,5.2399 9.6036,5.2889 9.4916,5.3129 9.3676,5.3129 9.2776,5.3129 9.1976,5.2989 9.1246,5.2719 9.0516,5.2439 8.9906,5.2069 8.9396,5.1579 8.8896,5.1109 8.8506,5.0529 8.8236,4.9859 8.7956,4.9179 8.7826,4.8459 8.7826,4.7679 8.7826,4.6819 8.7916,4.6039 8.8096,4.5349 8.8276,4.4669 8.8606,4.4079 8.9076,4.3559 8.9546,4.3029 9.0196,4.2579 9.1026,4.2229 9.1856,4.1899 9.2916,4.1619 9.4226,4.1449L10.1836,4.0349z M10.6296,2.3609C10.5186,2.2329 10.3766,2.1339 10.2056,2.0669 10.0356,1.9989 9.8316,1.9649 9.5976,1.9649 9.4786,1.9649 9.3566,1.9769 9.2296,1.9989 9.1036,2.0219 8.9816,2.0489 8.8676,2.0839 8.7536,2.1179 8.6506,2.1539 8.5576,2.1929 8.4656,2.2349 8.3956,2.2719 8.3446,2.3069L8.3446,3.0739C8.5026,2.9429 8.6856,2.8399 8.8886,2.7619 9.0926,2.6839 9.3016,2.6449 9.5156,2.6449 9.7286,2.6449 9.8926,2.7069 10.0096,2.8299 10.1256,2.9549 10.1836,3.1539 10.1836,3.4299L9.1536,3.5839C8.9496,3.6109 8.7746,3.6619 8.6276,3.7359 8.4826,3.8109 8.3636,3.9019 8.2706,4.0159 8.1766,4.1269 8.1096,4.2539 8.0656,4.3969 8.0216,4.5389 7.9996,4.6939 7.9996,4.8579 7.9996,5.0269 8.0256,5.1799 8.0746,5.3199 8.1226,5.4609 8.1956,5.5799 8.2896,5.6819 8.3826,5.7809 8.4996,5.8599 8.6416,5.9159 8.7816,5.9729 8.9396,5.9999 9.1206,5.9999 9.3496,5.9999 9.5506,5.9469 9.7236,5.8399 9.8966,5.7349 10.0426,5.5799 10.1626,5.3769L10.1766,5.3769 10.1766,5.9059 10.9616,5.9059 10.9616,3.4689C10.9616,3.2309 10.9346,3.0179 10.8786,2.8319 10.8246,2.6489 10.7406,2.4899 10.6296,2.3609" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M3.1406,12.2573C3.0576,12.2923 2.9936,12.3373 2.9456,12.3903 2.8986,12.4433 2.8656,12.5013 2.8476,12.5703 2.8296,12.6383 2.8206,12.7163 2.8206,12.8023 2.8206,12.8803 2.8336,12.9523 2.8616,13.0213 2.8886,13.0873 2.9276,13.1463 2.9776,13.1933 3.0286,13.2413 3.0896,13.2783 3.1626,13.3063 3.2356,13.3333 3.3156,13.3473 3.4056,13.3473 3.5296,13.3473 3.6416,13.3233 3.7426,13.2753 3.8406,13.2263 3.9256,13.1593 3.9976,13.0753 4.0706,12.9913 4.1246,12.8923 4.1626,12.7803 4.2016,12.6673 4.2216,12.5463 4.2216,12.4153L4.2216,12.0693 3.4606,12.1793C3.3296,12.1963,3.2236,12.2243,3.1406,12.2573" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M10,11.0029C9.873,10.9109 9.735,10.8369 9.587,10.7809 9.44,10.7249 9.28,10.6969 9.107,10.6969 8.937,10.6969 8.778,10.7259 8.629,10.7849 8.48,10.8429 8.352,10.9279 8.243,11.0409 8.134,11.1519 8.049,11.2909 7.986,11.4549 7.924,11.6189 7.892,11.8069 7.892,12.0179 7.892,12.2149 7.92,12.3919 7.975,12.5499 8.03,12.7079 8.109,12.8419 8.213,12.9509 8.316,13.0609 8.442,13.1459 8.59,13.2049 8.737,13.2649 8.905,13.2949 9.092,13.2949 9.167,13.2949 9.245,13.2859 9.325,13.2689 9.405,13.2509 9.484,13.2279 9.563,13.1989 9.642,13.1709 9.719,13.1369 9.794,13.0989 9.869,13.0599 9.937,13.0189 10,12.9739L10,13.7459C9.865,13.8229 9.709,13.8849 9.533,13.9309 9.357,13.9769 9.149,13.9999 8.908,13.9999 8.616,13.9999 8.352,13.9519 8.117,13.8569 7.882,13.7609 7.682,13.6279 7.517,13.4569 7.352,13.2869 7.226,13.0849 7.137,12.8529 7.048,12.6199 7.003,12.3679 7.003,12.0969 7.003,11.7779 7.052,11.4899 7.148,11.2309 7.244,10.9719 7.382,10.7509 7.562,10.5679 7.742,10.3849 7.96,10.2439 8.217,10.1429 8.473,10.0419 8.76,9.9919 9.078,9.9919 9.18,9.9919 9.277,9.9979 9.37,10.0099 9.463,10.0229 9.548,10.0389 9.627,10.0569 9.706,10.0759 9.777,10.0959 9.841,10.1189 9.904,10.1409 9.958,10.1639 10,10.1859z M5,13.9409L4.215,13.9409 4.215,13.4119 4.201,13.4119C4.081,13.6149 3.935,13.7689 3.762,13.8749 3.589,13.9819 3.388,14.0349 3.158,14.0349 2.978,14.0349 2.819,14.0069 2.68,13.9509 2.538,13.8939 2.421,13.8159 2.328,13.7159 2.233,13.6149 2.161,13.4959 2.112,13.3549 2.063,13.2139 2.038,13.0619 2.038,12.8919 2.038,12.7279 2.06,12.5739 2.104,12.4309 2.147,12.2889 2.215,12.1619 2.309,12.0499 2.401,11.9369 2.521,11.8449 2.666,11.7709 2.812,11.6969 2.987,11.6459 3.191,11.6189L4.222,11.4639C4.222,11.1889 4.164,10.9899 4.048,10.8649 3.931,10.7419 3.767,10.6789 3.554,10.6789 3.34,10.6789 3.131,10.7179 2.927,10.7959 2.724,10.8749 2.541,10.9779 2.383,11.1089L2.383,10.3409C2.434,10.3059 2.504,10.2689 2.596,10.2279 2.688,10.1889 2.792,10.1519 2.905,10.1179 3.02,10.0839 3.142,10.0569 3.268,10.0329 3.395,10.0119 3.517,9.9999 3.636,9.9999 3.87,9.9999 4.073,10.0329 4.244,10.1019 4.415,10.1689 4.557,10.2669 4.668,10.3959 4.778,10.5249 4.862,10.6829 4.917,10.8669 4.973,11.0519 5,11.2649 5,11.5029z M1,14.9999L11,14.9999 11,8.9999 1,8.9999z M1,8.9999" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M14.2217,4.4687C14.1827,4.6487 14.1267,4.7967 14.0537,4.9137 13.9817,5.0317 13.8937,5.1207 13.7897,5.1797 13.6857,5.2397 13.5707,5.2717 13.4407,5.2717 13.3327,5.2717 13.2317,5.2457 13.1397,5.1957 13.0487,5.1467 12.9697,5.0757 12.9027,4.9887 12.8357,4.9027 12.7847,4.7987 12.7477,4.6817 12.7107,4.5647 12.6917,4.4377 12.6917,4.3007L12.6917,3.7947C12.6917,3.6247 12.7117,3.4687 12.7517,3.3297 12.7917,3.1917 12.8477,3.0727 12.9197,2.9707 12.9927,2.8707 13.0757,2.7927 13.1767,2.7387 13.2767,2.6837 13.3867,2.6557 13.5077,2.6557 13.6297,2.6557 13.7397,2.6837 13.8347,2.7387 13.9307,2.7927 14.0117,2.8727 14.0787,2.9767 14.1457,3.0817 14.1957,3.2067 14.2297,3.3537 14.2637,3.4997 14.2817,3.6637 14.2817,3.8477 14.2817,4.0817 14.2617,4.2887 14.2217,4.4687 M14.9257,3.1267C14.8757,2.8947 14.8007,2.6917 14.6987,2.5157 14.5947,2.3397 14.4627,2.2007 14.3037,2.0997 14.1437,1.9967 13.9517,1.9467 13.7307,1.9467 13.6077,1.9467 13.4957,1.9637 13.3947,1.9987 13.2917,2.0337 13.2007,2.0827 13.1167,2.1447 13.0327,2.2067 12.9577,2.2807 12.8907,2.3667 12.8257,2.4547 12.7637,2.5507 12.7097,2.6557L12.6977,2.6557 12.6977,0.9997 11.9997,0.9997 11.9997,5.8867 12.6977,5.8867 12.6977,5.4027 12.7097,5.4027C12.7537,5.4847 12.8047,5.5607 12.8617,5.6307 12.9177,5.7007 12.9807,5.7637 13.0527,5.8167 13.1237,5.8687 13.2037,5.9077 13.2907,5.9377 13.3787,5.9667 13.4767,5.9807 13.5827,5.9807 13.8137,5.9807 14.0167,5.9277 14.1927,5.8207 14.3677,5.7147 14.5157,5.5667 14.6357,5.3767 14.7557,5.1897 14.8467,4.9647 14.9087,4.7047 14.9687,4.4457 14.9997,4.1657 14.9997,3.8617 14.9997,3.6037 14.9747,3.3597 14.9257,3.1267" />
<GeometryDrawing Brush="#FF414141" Geometry="F1M1.9785,3.5L1.9995,6 0.9995,5 0.9995,6.5 2.4995,8 3.9995,6.5 3.9995,5 2.9995,6 2.9785,3.5C2.9785,3.225,3.2035,3,3.4785,3L6.9995,3 6.9995,2 3.4785,2C2.6515,2,1.9785,2.673,1.9785,3.5" />
<GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M4.2217,12.4155C4.2217,12.5465 4.2007,12.6675 4.1627,12.7805 4.1247,12.8925 4.0707,12.9915 3.9977,13.0755 3.9257,13.1595 3.8407,13.2265 3.7427,13.2745 3.6417,13.3235 3.5297,13.3475 3.4057,13.3475 3.3157,13.3475 3.2357,13.3335 3.1627,13.3065 3.0897,13.2785 3.0287,13.2415 2.9777,13.1925 2.9277,13.1455 2.8887,13.0875 2.8617,13.0205 2.8337,12.9525 2.8207,12.8805 2.8207,12.8025 2.8207,12.7165 2.8297,12.6385 2.8477,12.5695 2.8657,12.5015 2.8987,12.4425 2.9457,12.3905 2.9927,12.3375 3.0577,12.2925 3.1407,12.2575 3.2237,12.2245 3.3297,12.1965 3.4607,12.1795L4.2217,12.0695z M4.6677,10.3955C4.5567,10.2675 4.4147,10.1685 4.2437,10.1015 4.0737,10.0335 3.8697,9.9995 3.6357,9.9995 3.5167,9.9995 3.3947,10.0115 3.2677,10.0335 3.1417,10.0565 3.0197,10.0835 2.9057,10.1185 2.7917,10.1525 2.6887,10.1885 2.5957,10.2275 2.5037,10.2695 2.4337,10.3065 2.3827,10.3415L2.3827,11.1085C2.5407,10.9775 2.7237,10.8745 2.9267,10.7965 3.1307,10.7185 3.3397,10.6795 3.5537,10.6795 3.7667,10.6795 3.9307,10.7415 4.0477,10.8645 4.1637,10.9895 4.2217,11.1885 4.2217,11.4645L3.1917,11.6185C2.9877,11.6455 2.8127,11.6965 2.6657,11.7705 2.5207,11.8455 2.4017,11.9365 2.3087,12.0505 2.2147,12.1615 2.1477,12.2885 2.1037,12.4315 2.0597,12.5735 2.0377,12.7285 2.0377,12.8925 2.0377,13.0615 2.0637,13.2145 2.1127,13.3545 2.1607,13.4955 2.2337,13.6145 2.3277,13.7165 2.4207,13.8155 2.5377,13.8945 2.6797,13.9505 2.8197,14.0075 2.9777,14.0345 3.1587,14.0345 3.3877,14.0345 3.5887,13.9815 3.7617,13.8745 3.9347,13.7695 4.0807,13.6145 4.2007,13.4115L4.2147,13.4115 4.2147,13.9405 4.9997,13.9405 4.9997,11.5035C4.9997,11.2655 4.9727,11.0525 4.9167,10.8665 4.8627,10.6835 4.7787,10.5245 4.6677,10.3955" />
<GeometryDrawing Brush="#FFF0EFF1" Geometry="F1M9.627,10.0571C9.548,10.0381 9.463,10.0231 9.37,10.0101 9.277,9.9981 9.18,9.9921 9.078,9.9921 8.76,9.9921 8.473,10.0421 8.217,10.1431 7.96,10.2441 7.742,10.3851 7.563,10.5681 7.382,10.7511 7.244,10.9721 7.148,11.2311 7.052,11.4901 7.003,11.7781 7.003,12.0971 7.003,12.3681 7.048,12.6201 7.137,12.8521 7.226,13.0851 7.352,13.2861 7.517,13.4571 7.682,13.6271 7.882,13.7611 8.117,13.8561 8.352,13.9521 8.616,14.0001 8.908,14.0001 9.149,14.0001 9.357,13.9771 9.533,13.9311 9.71,13.8851 9.865,13.8231 10,13.7461L10,12.9741C9.938,13.0181 9.869,13.0601 9.794,13.0991 9.719,13.1371 9.642,13.1711 9.563,13.1991 9.484,13.2281 9.405,13.2511 9.325,13.2681 9.245,13.2861 9.167,13.2941 9.092,13.2941 8.905,13.2941 8.737,13.2651 8.59,13.2051 8.442,13.1451 8.316,13.0601 8.213,12.9511 8.109,12.8421 8.03,12.7081 7.975,12.5501 7.92,12.3921 7.892,12.2151 7.892,12.0181 7.892,11.8071 7.924,11.6191 7.986,11.4541 8.049,11.2901 8.134,11.1521 8.243,11.0401 8.352,10.9281 8.481,10.8431 8.629,10.7851 8.778,10.7261 8.938,10.6971 9.107,10.6971 9.28,10.6971 9.44,10.7251 9.587,10.7811 9.735,10.8371 9.873,10.9111 10,11.0031L10,10.1851C9.958,10.1631 9.904,10.1411 9.841,10.1191 9.777,10.0961 9.706,10.0761 9.627,10.0571" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="ExpandChevronDown">
<DrawingImage.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
<GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M7.7393,10.9297L2.7573,5.9427 5.0693,3.6287 7.7983,6.3617 10.7633,3.6617 13.0703,5.9677z" />
<GeometryDrawing Brush="#FF424242" Geometry="F1M5.0683,5.044L4.1703,5.942 7.7643,9.54 11.6303,5.942 10.7313,5.044 7.7643,7.743z" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<Style x:Key="ExpanderToggle" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Image x:Name="Image" RenderTransformOrigin=".5 .5" Source="{StaticResource ExpandChevronDown}" />
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Image" Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleY="-1" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.9" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="SRPanelTemplate" TargetType="editor:SearchReplacePanel">
<Border
HorizontalAlignment="Right"
VerticalAlignment="Top"
Background="#eeeeee"
BorderBrush="DarkGray"
BorderThickness="0,0,0,3"
Cursor="Arrow"
TextElement.FontFamily="{x:Static SystemFonts.MenuFontFamily}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ToggleButton
Grid.Row="0"
Grid.Column="0"
Width="16"
Margin="2"
IsChecked="{Binding IsReplaceMode, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ExpanderToggle}"
ToolTip="切换查找/替换模式" />
<TextBox
Name="PART_searchTextBox"
Grid.Row="0"
Grid.Column="1"
Width="150"
Margin="3,3,3,0"
Style="{StaticResource MaterialDesignTextBox}"
Text="{Binding SearchPattern, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}" />
<TextBox
Name="ReplaceBox"
Grid.Row="1"
Grid.Column="1"
Width="150"
Margin="3,3,3,0"
Style="{StaticResource MaterialDesignTextBox}"
Text="{Binding ReplacePattern, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"
Visibility="Collapsed" />
<StackPanel Grid.Row="0" Grid.Column="2" Orientation="Horizontal">
<avalonedit:DropDownButton Height="24">
<avalonedit:DropDownButton.DropDownContent>
<Popup StaysOpen="False">
<Border Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" BorderThickness="1">
<StackPanel Orientation="Vertical">
<CheckBox
Margin="3"
Content="区分大小写"
IsChecked="{Binding MatchCase, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource MaterialDesignLightCheckBox}" />
<CheckBox
Margin="3"
Content="全字匹配"
IsChecked="{Binding WholeWords, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource MaterialDesignLightCheckBox}" />
<CheckBox
Margin="3"
Content="使用正则表达式"
IsChecked="{Binding UseRegex, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource MaterialDesignLightCheckBox}" />
</StackPanel>
</Border>
</Popup>
</avalonedit:DropDownButton.DropDownContent>
</avalonedit:DropDownButton>
<Button
Margin="3"
Command="avalonedit:SearchCommands.FindPrevious"
Style="{StaticResource MaterialDesignToolButton}"
ToolTip="查找上一个">
<Image Source="{StaticResource FindPrevious}" Stretch="Fill" />
</Button>
<Button
Margin="3"
Command="avalonedit:SearchCommands.FindNext"
Style="{StaticResource MaterialDesignToolButton}"
ToolTip="查找下一个">
<Image Source="{StaticResource FindNext}" Stretch="Fill" />
</Button>
<Button
HorizontalAlignment="Right"
VerticalAlignment="Top"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Command="avalonedit:SearchCommands.CloseSearchPanel"
Focusable="False"
Style="{StaticResource MaterialDesignToolButton}">
<Path Data="M 0,0 L 8,8 M 8,0 L 0,8" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" />
</Button>
</StackPanel>
<StackPanel
Name="ReplaceButtons"
Grid.Row="1"
Grid.Column="2"
Orientation="Horizontal"
Visibility="Collapsed">
<Button
Margin="3"
Command="editor:SearchCommandsEx.ReplaceNext"
Style="{StaticResource MaterialDesignToolButton}"
ToolTip="替换下一个(Alt+R)">
<Image
Width="16"
Height="16"
Source="{StaticResource ReplaceNext}"
Stretch="Fill" />
</Button>
<Button
Margin="3"
Command="editor:SearchCommandsEx.ReplaceAll"
Style="{StaticResource MaterialDesignToolButton}"
ToolTip="替换全部(Alt+A)">
<Image
Width="16"
Height="16"
Source="{StaticResource ReplaceAll}"
Stretch="Fill" />
</Button>
</StackPanel>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsReplaceMode" Value="True">
<Setter TargetName="ReplaceBox" Property="Visibility" Value="Visible" />
<Setter TargetName="ReplaceButtons" Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="editor:SearchReplacePanel">
<Setter Property="FontSize" Value="{x:Static SystemFonts.MessageFontSize}" />
<Setter Property="FontFamily" Value="{x:Static SystemFonts.MessageFontFamily}" />
<Setter Property="Template" Value="{DynamicResource SRPanelTemplate}" />
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,24 @@
using ColorCode.Styling;
#nullable enable
namespace Markdig.Wpf.ColorCode;
/// <summary>
/// Extensions for adding ColorCode to the Markdig pipeline.
/// </summary>
public static class MarkdownPipelineBuilderExtension
{
/// <summary>
/// Use ColorCode to apply code colorization to markdown within the Markdig pipeline.
/// </summary>
/// <param name="pipeline">The pipeline the ColorCode extension is being added to.</param>
/// <param name="styleDictionary">An optional StyleDictionary for custom styling.</param>
/// <returns>The MarkdownPipelineBuilder with the added ColorCode extension.</returns>
public static MarkdownPipelineBuilder UseColorCodeWpf(
this MarkdownPipelineBuilder pipeline,
StyleDictionary? styleDictionary = null)
{
pipeline.Extensions.Add(new ColorCodeWpfExtension(styleDictionary ?? StyleDictionary.DefaultLight));
return pipeline;
}
}

View File

@@ -0,0 +1,111 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:markdig="clr-namespace:Markdig.Wpf;assembly=Markdig.Wpf">
<!-- Document styles -->
<Style x:Key="{x:Static markdig:Styles.DocumentStyleKey}" TargetType="{x:Type FlowDocument}">
<Setter Property="FontFamily" Value="Microsoft YaHei UI" />
<Setter Property="TextAlignment" Value="Left" />
<Setter Property="Foreground" Value="#dddddd" />
<Setter Property="LineHeight" Value="5" />
<Setter Property="FontSize" Value="12" />
</Style>
<Style TargetType="{x:Type List}">
<Setter Property="Margin" Value="40,0,0,0" />
<Setter Property="Padding" Value="0,0,0,0" />
</Style>
<Style x:Key="{x:Static markdig:Styles.CodeBlockStyleKey}" TargetType="{x:Type Paragraph}">
<Setter Property="Background" Value="#0CFFFFFF" />
<Setter Property="BorderBrush" Value="#3d3d3d" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="FontFamily" Value="Consolas, Lucida Sans Typewriter, Courier New" />
</Style>
<Style x:Key="{x:Static markdig:Styles.CodeStyleKey}" TargetType="{x:Type Run}">
<Setter Property="Background" Value="#8C6699FF" />
<Setter Property="FontFamily" Value="Consolas, Lucida Sans Typewriter, Courier New" />
</Style>
<Style x:Key="{x:Static markdig:Styles.Heading1StyleKey}" TargetType="{x:Type Paragraph}">
<Setter Property="FontSize" Value="24" />
<Setter Property="Foreground" Value="#69f" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style x:Key="{x:Static markdig:Styles.Heading2StyleKey}" TargetType="{x:Type Paragraph}">
<Setter Property="FontSize" Value="18" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="#69f" />
</Style>
<Style x:Key="{x:Static markdig:Styles.Heading3StyleKey}" TargetType="{x:Type Paragraph}">
<Setter Property="FontSize" Value="16" />
<Setter Property="Foreground" Value="#69f" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style x:Key="{x:Static markdig:Styles.Heading4StyleKey}" TargetType="{x:Type Paragraph}">
<Setter Property="FontSize" Value="14" />
<Setter Property="Foreground" Value="#69f" />
<Setter Property="FontWeight" Value="Light" />
<Setter Property="TextDecorations" Value="Underline" />
</Style>
<Style x:Key="{x:Static markdig:Styles.Heading5StyleKey}" TargetType="{x:Type Paragraph}">
<!-- no changes -->
</Style>
<Style x:Key="{x:Static markdig:Styles.Heading6StyleKey}" TargetType="{x:Type Paragraph}">
<!-- no changes -->
</Style>
<Style x:Key="{x:Static markdig:Styles.HyperlinkStyleKey}" TargetType="{x:Type Hyperlink}">
<!-- no changes -->
</Style>
<Style x:Key="{x:Static markdig:Styles.ImageStyleKey}" TargetType="{x:Type Image}">
<Setter Property="MaxHeight" Value="{Binding RelativeSource={RelativeSource Self}, Path=Source.(BitmapSource.PixelHeight)}" />
<Setter Property="MaxWidth" Value="{Binding RelativeSource={RelativeSource Self}, Path=Source.(BitmapSource.PixelWidth)}" />
</Style>
<Style x:Key="{x:Static markdig:Styles.QuoteBlockStyleKey}" TargetType="{x:Type Section}">
<Setter Property="BorderBrush" Value="#8C6699FF" />
<Setter Property="BorderThickness" Value="4,0,0,0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Padding" Value="16,0,0,0" />
</Style>
<Style x:Key="{x:Static markdig:Styles.TableStyleKey}" TargetType="{x:Type Table}">
<Setter Property="BorderBrush" Value="#3d3d3d" />
<Setter Property="BorderThickness" Value="0,0,1,1" />
<Setter Property="CellSpacing" Value="0" />
</Style>
<Style x:Key="{x:Static markdig:Styles.TableCellStyleKey}" TargetType="{x:Type TableCell}">
<Setter Property="BorderBrush" Value="#3d3d3d" />
<Setter Property="Background" Value="#0CFFFFFF" />
<Setter Property="BorderThickness" Value="1,1,0,0" />
</Style>
<Style x:Key="{x:Static markdig:Styles.TableHeaderStyleKey}" TargetType="{x:Type TableRow}">
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style x:Key="{x:Static markdig:Styles.TaskListStyleKey}" TargetType="{x:Type CheckBox}">
<Setter Property="Margin" Value="0,0,0,-2" />
</Style>
<Style x:Key="{x:Static markdig:Styles.ThematicBreakStyleKey}" TargetType="{x:Type Line}">
<Setter Property="Stretch" Value="Fill" />
<Setter Property="Stroke" Value="#c5c5c5" />
</Style>
<Style x:Key="{x:Static markdig:Styles.SubscriptStyleKey}" TargetType="{x:Type Span}">
<Setter Property="Typography.Variants" Value="Subscript" />
</Style>
<Style x:Key="{x:Static markdig:Styles.SuperscriptStyleKey}" TargetType="{x:Type Span}">
<Setter Property="Typography.Variants" Value="Superscript" />
</Style>
<Style x:Key="{x:Static markdig:Styles.StrikeThroughStyleKey}" TargetType="{x:Type Span}">
<Setter Property="TextBlock.TextDecorations" Value="Strikethrough" />
</Style>
<Style x:Key="{x:Static markdig:Styles.InsertedStyleKey}" TargetType="{x:Type Span}">
<Setter Property="TextBlock.TextDecorations" Value="Underline" />
</Style>
<Style x:Key="{x:Static markdig:Styles.MarkedStyleKey}" TargetType="{x:Type Span}">
<Setter Property="Background" Value="Yellow" />
</Style>
<!-- MarkdownViewer Template -->
<Style TargetType="{x:Type markdig:MarkdownViewer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type markdig:MarkdownViewer}">
<FlowDocumentScrollViewer Document="{TemplateBinding Document}" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,44 @@
using System.Collections.Immutable;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using RoslynPad.Roslyn;
namespace Szmedi.RvKits.RvScript
{
public class RevitRoslynHost : RoslynHost
{
public RevitRoslynHost(IEnumerable<Assembly> additionalAssemblies = null, RoslynHostReferences references = null, ImmutableArray<string>? disabledDiagnostics = null) : base(additionalAssemblies, references, disabledDiagnostics)
{
}
protected override Project CreateProject(Solution solution, DocumentCreationArgs args, CompilationOptions compilationOptions, Project previousProject = null)
{
var name = args.Name ?? "Program";
var id = ProjectId.CreateNewId(name);
var parseOptions = new CSharpParseOptions(kind: SourceCodeKind.Script, languageVersion: LanguageVersion.Default);
compilationOptions = compilationOptions.WithScriptClassName(name);
solution = solution.AddProject(ProjectInfo.Create(
id,
VersionStamp.Create(),
name,
name,
LanguageNames.CSharp,
isSubmission: true,
parseOptions: parseOptions,
hostObjectType: typeof(ScriptGlobals),
compilationOptions: compilationOptions,
metadataReferences: previousProject != null ? ImmutableArray<MetadataReference>.Empty : DefaultReferences,
projectReferences: previousProject != null ? new[] { new ProjectReference(previousProject.Id) } : null));
var project = solution.GetProject(id);
return project;
}
}
}

View File

@@ -0,0 +1,148 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using ColorCode.Common;
using ColorCode.Parsing;
using ColorCode.Styling;
using ColorCode.Wpf.Common;
#nullable enable
namespace ColorCode.Wpf
{
/// <summary>
/// Creates a <see cref="RichTextBoxFormatter"/>, for rendering Syntax Highlighted code to a RichTextBlock.
/// </summary>
public class RichTextBoxFormatter : CodeColorizerBase
{
/// <summary>
/// Creates a <see cref="RichTextBoxFormatter"/>, for rendering Syntax Highlighted code to a RichTextBlock.
/// </summary>
/// <param name="style">The Custom styles to Apply to the formatted Code.</param>
/// <param name="languageParser">The language parser that the <see cref="RichTextBoxFormatter"/> instance will use for its lifetime.</param>
public RichTextBoxFormatter(StyleDictionary? style = null, ILanguageParser? languageParser = null) : base(style, languageParser)
{
}
/// <summary>
/// Adds Syntax Highlighted Source Code to the provided RichTextBlock.
/// </summary>
/// <param name="sourceCode">The source code to colorize.</param>
/// <param name="language">The language to use to colorize the source code.</param>
/// <param name="richText">The Control to add the Text to.</param>
public void FormatRichTextBox(string sourceCode, ILanguage language, RichTextBox richText)
{
var paragraph = new Paragraph();
richText.Document.Blocks.Add(paragraph);
FormatInlines(sourceCode, language, paragraph.Inlines);
}
/// <summary>
/// Adds Syntax Highlighted Source Code to the provided InlineCollection.
/// </summary>
/// <param name="sourceCode">The source code to colorize.</param>
/// <param name="language">The language to use to colorize the source code.</param>
/// <param name="inlineCollection">InlineCollection to add the Text to.</param>
public void FormatInlines(string sourceCode, ILanguage language, InlineCollection inlineCollection)
{
InlineCollection = inlineCollection;
languageParser.Parse(sourceCode, language, (parsedSourceCode, captures) => Write(parsedSourceCode, captures));
}
private InlineCollection? InlineCollection { get; set; }
protected override void Write(string parsedSourceCode, IList<Scope> scopes)
{
var styleInsertions = new List<TextInsertion>();
foreach (Scope scope in scopes)
GetStyleInsertionsForCapturedStyle(scope, styleInsertions);
styleInsertions.SortStable((x, y) => x.Index.CompareTo(y.Index));
int offset = 0;
Scope? previousScope = null;
foreach (var styleinsertion in styleInsertions)
{
var text = parsedSourceCode.Substring(offset, styleinsertion.Index - offset);
CreateSpan(text, previousScope);
if (!string.IsNullOrWhiteSpace(styleinsertion.Text))
{
CreateSpan(text, previousScope);
}
offset = styleinsertion.Index;
previousScope = styleinsertion.Scope;
}
var remaining = parsedSourceCode.Substring(offset);
// Ensures that those loose carriages don't run away!
if (remaining != "\r")
{
CreateSpan(remaining, null);
}
}
private void CreateSpan(string text, Scope? scope)
{
var span = new Span();
var run = new Run
{
Text = text
};
// Styles and writes the text to the span.
if (scope != null) StyleRun(run, scope);
span.Inlines.Add(run);
InlineCollection?.Add(span);
}
private void StyleRun(Run run, Scope scope)
{
string? foreground = null;
string? background = null;
bool italic = false;
bool bold = false;
if (Styles.Contains(scope.Name))
{
Styling.Style style = Styles[scope.Name];
foreground = style.Foreground;
background = style.Background;
italic = style.Italic;
bold = style.Bold;
}
if (!string.IsNullOrWhiteSpace(foreground))
run.Foreground = foreground.GetSolidColorBrush();
//Background isn't supported, but a workaround could be created.
if (italic)
run.FontStyle = FontStyles.Italic;
if (bold)
run.FontWeight = FontWeights.Bold;
}
private void GetStyleInsertionsForCapturedStyle(Scope scope, ICollection<TextInsertion> styleInsertions)
{
styleInsertions.Add(new TextInsertion
{
Index = scope.Index,
Scope = scope
});
foreach (Scope childScope in scope.Children)
GetStyleInsertionsForCapturedStyle(childScope, styleInsertions);
styleInsertions.Add(new TextInsertion
{
Index = scope.Index + scope.Length
});
}
}
}

View File

@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using LangChain.Providers;
namespace Szmedi.RvKits.RvScript
{
internal class RoleToDisplayConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is MessageRole role)
{
switch (role)
{
case MessageRole.System:
break;
case MessageRole.Human:
if (targetType == typeof(HorizontalAlignment))
{
return HorizontalAlignment.Right;
}
else if (targetType == typeof(Brush))
{
var UserMessgeBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#785dc8"));
return UserMessgeBrush;
}
else if (targetType == typeof(Visibility))
{
return Visibility.Collapsed;
}
break;
case MessageRole.Ai:
if (targetType == typeof(HorizontalAlignment))
{
return HorizontalAlignment.Left;
}
else if (targetType == typeof(Brush))
{
var ModelMessageBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#292E33"));
return ModelMessageBrush;
}
else if (targetType == typeof(Visibility))
{
return Visibility.Visible;
}
break;
case MessageRole.Chat:
break;
case MessageRole.ToolCall:
break;
case MessageRole.ToolResult:
break;
default:
break;
}
}
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,277 @@
<controls:MaterialWindow x:Class="Szmedi.RvKits.RvScript.RoslynEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avalonDock="https://github.com/Dirkster99/AvalonDock"
xmlns:codeActions="clr-namespace:Microsoft.CodeAnalysis.CodeActions;assembly=Microsoft.CodeAnalysis.Workspaces"
xmlns:codeFixes="clr-namespace:RoslynPad.Roslyn.CodeFixes;assembly=RoslynPad.Roslyn"
xmlns:controls="clr-namespace:Szmedi.RvKits.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:editor="clr-namespace:RoslynPad.Editor;assembly=RoslynPad.Editor.Windows"
xmlns:local="clr-namespace:Szmedi.RvKits.RvScript"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
Width="800"
Background="{DynamicResource MaterialDesign.Brush.Background}"
Height="500"
mc:Ignorable="d"
Closing="Window_Closing"
d:DataContext="{d:DesignInstance local:RoslynEditorViewModel}"
ResizeMode="CanResize"
SizeToContent="Manual"
Title="C#脚本执行">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Szmedi.RvKits;component/Icons.xaml" />
<ResourceDictionary Source="pack://application:,,,/Szmedi.RvKits;component/WPFUI.xaml" />
</ResourceDictionary.MergedDictionaries>
<HierarchicalDataTemplate DataType="{x:Type codeFixes:CodeFixCollection}" ItemsSource="{Binding Fixes, Mode=OneTime}">
<TextBlock Text="{Binding Provider, Mode=OneTime}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type codeFixes:CodeFix}" ItemsSource="{Binding Action,
Mode=OneTime,
Converter={local:CodeActionsConverter}}">
<ContentPresenter Content="{Binding Action, Mode=OneTime}" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type codeActions:CodeAction}">
<TextBlock Text="{Binding Title, Mode=OneTime}" />
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
<Window.InputBindings>
<KeyBinding Key="F5" Command="{Binding ActiveDocument.RunCommand}" />
<KeyBinding Command="{Binding ActiveDocument.SaveCommand}" Gesture="Ctrl+S" />
<KeyBinding Command="{Binding ActiveDocument.FormatCommand}" Gesture="Ctrl+F8" />
</Window.InputBindings>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="30" />
<ColumnDefinition Width="2" />
<ColumnDefinition Width="0.6*" MinWidth="20" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" MinHeight="20" />
<RowDefinition Height="2" />
<RowDefinition Height="60" MinHeight="60" />
</Grid.RowDefinitions>
<!-- <StackPanel HorizontalAlignment="Left" Grid.Column="0">
<Button Name="ScriptRunner" Click="ScriptRunner_Click">Run Script</Button>
</StackPanel> -->
<DockPanel Grid.Row="0" Grid.Column="0">
<Menu DockPanel.Dock="Top">
<MenuItem Header="文件">
<MenuItem Command="{Binding NewCommand}" Header="新建脚本">
<MenuItem.Icon>
<md:PackIcon Kind="File" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Command="{Binding OpenCommand}" Header="打开脚本">
<MenuItem.Icon>
<md:PackIcon Kind="OpenInNew" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Command="{Binding ActiveDocument.SaveCommand}" Header="保存">
<MenuItem.Icon>
<md:PackIcon Kind="ContentSave" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Command="{Binding ActiveDocument.SaveAsCommand}" Header="另存为">
<MenuItem.Icon>
<md:PackIcon Kind="ContentSaveAdd" />
</MenuItem.Icon>
</MenuItem>
<!-- <MenuItem Header="退出">
<MenuItem.Icon>
<md:PackIcon Kind="ExitRun" />
</MenuItem.Icon>
</MenuItem> -->
</MenuItem>
<MenuItem Header="运行">
<MenuItem Command="{Binding ActiveDocument.RunCommand}" Header="执行脚本">
<MenuItem.Icon>
<md:PackIcon Kind="Play" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="帮助">
<MenuItem Command="{Binding AboutCommand}" Header="关于">
<MenuItem.Icon>
<md:PackIcon Kind="Information" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
</DockPanel>
<ToolBar Grid.Row="1">
<Button x:Name="New"
Command="{Binding NewCommand}"
ToolTip="新建脚本">
<md:PackIcon Kind="File" />
<!-- <ContentControl Template="{StaticResource ResourceKey=NewFile}" ToolTip="新建脚本" /> -->
</Button>
<Button x:Name="Open_Script"
Command="{Binding OpenCommand}"
ToolTip="打开脚本">
<!-- <md:PackIcon Kind="OpenInApp" /> -->
<Image Width="16"
Height="16"
Source="{StaticResource OpenSciptFile}" />
<!-- <ContentControl Template="{StaticResource ResourceKey=OpenFile}" ToolTip="打开脚本" /> -->
</Button>
<Separator />
<Button x:Name="Save"
Command="{Binding ActiveDocument.SaveCommand}"
ToolTip="保存脚本">
<md:PackIcon Kind="ContentSave" />
<!-- <ContentControl Template="{StaticResource ResourceKey=SaveFile}" ToolTip="保存脚本" /> -->
</Button>
<Button x:Name="Save_As"
Command="{Binding ActiveDocument.SaveAsCommand}"
ToolTip="另存为脚本">
<md:PackIcon Kind="ContentSaveAdd" />
<!-- <ContentControl Template="{StaticResource ResourceKey=SaveAsFile}" ToolTip="另存为脚本" /> -->
</Button>
<Button Command="Undo" ToolTip="撤销">
<md:PackIcon Kind="Undo" />
</Button>
<Button Command="Redo" ToolTip="重做">
<md:PackIcon Kind="Redo" />
</Button>
<Button Command="{Binding ActiveDocument.CommentCommand}"
CommandParameter="{Binding ElementName=dockManager}"
Name="CommentBtn"
ToolTip="注释">
<Image Width="22"
Height="22"
Source="{StaticResource Comments}" />
<!-- <md:PackIcon Kind="CommentOutline" /> -->
</Button>
<Button Command="{Binding ActiveDocument.UnCommentCommand}"
CommandParameter="{Binding ElementName=dockManager}"
Name="UnCommentBtn"
ToolTip="取消注释">
<!-- <md:PackIcon Kind="CommentOffOutline" /> -->
<Image Width="22"
Height="22"
Source="{StaticResource UnComments}" />
</Button>
<Button Command="{Binding ActiveDocument.FormatCommand}"
Name="formatBtn"
ToolTip="格式化脚本">
<!-- <md:PackIcon Kind="FormatText" /> -->
<Image Width="22"
Height="22"
Source="{StaticResource FormatCode}" />
</Button>
<!-- <Button x:Name="CloseScript" Command="{Binding ActiveDocument.CloseCommand}" Content="关闭脚本" /> -->
<Separator />
<Button x:Name="Run"
Command="{Binding ActiveDocument.RunCommand}"
ToolTip="运行脚本">
<md:PackIcon Kind="Play" />
</Button>
</ToolBar>
<ProgressBar Grid.Row="2"
Height="5"
IsIndeterminate="True"
Visibility="{Binding IsRunning}" />
<avalonDock:DockingManager x:Name="dockManager"
Grid.Row="3"
ActiveContent="{Binding ActiveDocument, Mode=TwoWay}"
Background="{DynamicResource MaterialDesign.Brush.Background}"
DocumentClosing="dockManager_DocumentClosing"
DocumentsSource="{Binding Documents}"
TextElement.Foreground="{DynamicResource MaterialDesign.Brush.Foreground}">
<avalonDock:DockingManager.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Szmedi.RvKits;component/RvScript/Generic.xaml" />
<ResourceDictionary Source="pack://application:,,,/AvalonDock.Themes.VS2013;component/DarkTheme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</avalonDock:DockingManager.Resources>
<avalonDock:DockingManager.DocumentHeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{Binding Content.FileName, Mode=OneWay}"
TextTrimming="CharacterEllipsis" />
</StackPanel>
</DataTemplate>
</avalonDock:DockingManager.DocumentHeaderTemplate>
<avalonDock:DockingManager.LayoutItemTemplateSelector>
<local:DocumentTemplateSelector>
<local:DocumentTemplateSelector.DocumentViewTemplate>
<DataTemplate>
<editor:RoslynCodeEditor x:Name="CodeEditor"
IsModified="{Binding IsDirty,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
IsReadOnly="{Binding IsReadOnly}"
Loaded="CodeEditor_Loaded" />
<!-- <ed:TextEditor
x:Name="CodeEditor"
IsModified="{Binding IsDirty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsReadOnly="{Binding IsReadOnly}"
Loaded="CodeEditor_Loaded" /> -->
</DataTemplate>
</local:DocumentTemplateSelector.DocumentViewTemplate>
</local:DocumentTemplateSelector>
</avalonDock:DockingManager.LayoutItemTemplateSelector>
<avalonDock:LayoutRoot>
<avalonDock:LayoutPanel Orientation="Vertical">
<avalonDock:LayoutDocumentPane />
</avalonDock:LayoutPanel>
</avalonDock:LayoutRoot>
</avalonDock:DockingManager>
<!-- <editor:RoslynCodeEditor x:Name="CodeEditor" SyntaxHighlighting="C#" Grid.Column="0" Grid.Row="1" ShowLineNumbers="False" Margin="5" Loaded="CodeEditor_Loaded"></editor:RoslynCodeEditor> -->
<GridSplitter Grid.Row="0"
Grid.RowSpan="4"
Grid.Column="1"
Width="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ResizeDirection="Columns" />
<local:ChatDialogue Grid.Row="0"
Grid.RowSpan="6"
Grid.Column="2"
MinWidth="300"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
<GridSplitter Grid.Row="4"
Height="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
<ScrollViewer Grid.Row="5"
Grid.Column="0"
VerticalScrollBarVisibility="Auto">
<TextBox IsReadOnly="True"
Text="{Binding Result}"
TextAlignment="Left" />
</ScrollViewer>
<StackPanel Grid.Row="5"
Grid.Column="2"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Orientation="Horizontal">
<Button Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Command="{Binding RunCodeCommand}"
ToolTip="直接执行对话中的代码">
<md:PackIcon Kind="Code" />
</Button>
<Button Margin="5"
Command="{Binding CopyCodeCommand}"
ToolTip="复制对话中的代码">
<md:PackIcon Kind="ContentCopy" />
</Button>
</StackPanel>
</Grid>
</controls:MaterialWindow>

View File

@@ -0,0 +1,78 @@
using System.Reflection;
using System.Windows;
using AvalonDock.Themes;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
using Microsoft.CodeAnalysis.Differencing;
using RoslynPad.Editor;
namespace Szmedi.RvKits.RvScript
{
/// <summary>
/// Interaction logic for RoslynEditor.xaml
/// </summary>
public partial class RoslynEditor
{
public RoslynEditor(RoslynEditorViewModel document)
{
InitializeComponent();
DataContext = document;
}
private void CodeEditor_Loaded(object sender, RoutedEventArgs e)
{
var editor = (RoslynCodeEditor)sender;
editor.Loaded -= CodeEditor_Loaded;
editor.Focus();
var viewModel = (RoslynEditorViewModel)DataContext;
viewModel.CodeEditor = editor;
var documentViewModel = (DocumentViewModel)editor.DataContext;
var workingDirectory = Directory.GetCurrentDirectory();
var documentId = editor.Initialize(viewModel.Host, new ClassificationHighlightColors(),
workingDirectory, string.Empty);
documentViewModel.Initialize(documentId);
editor.Document.TextChanged += documentViewModel.OnTextChanged;
}
private void dockManager_DocumentClosing(object sender, AvalonDock.DocumentClosingEventArgs e)
{
e.Cancel = true;
var documentViewModel = (DocumentViewModel)e.Document.Content;
var viewModel = (RoslynEditorViewModel)DataContext;
viewModel.Close(documentViewModel);
}
//private void Window_Closed(object sender, EventArgs e)
//{
// AppDomain.CurrentDomain.AssemblyResolve -= ScriptRunnerCmd.CurrentDomain_AssemblyResolve;
//}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (dockManager.ActiveContent is DocumentViewModel viewModel && viewModel.IsDirty)
{
var mes = MessageBox.Show("有文件未保存,确定关闭吗?", "关闭", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (mes == MessageBoxResult.No)
{
e.Cancel = true;
}
else
{
AppDomain.CurrentDomain.AssemblyResolve -= ScriptRunnerCmd.CurrentDomain_AssemblyResolve;
}
}
}
}
}

View File

@@ -0,0 +1,232 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Xml;
using Autodesk.Revit.UI;
using AvalonDock;
using CommunityToolkit.Mvvm.Messaging;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
using Markdig;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Differencing;
using Microsoft.Win32;
using RoslynPad.Editor;
namespace Szmedi.RvKits.RvScript
{
public partial class RoslynEditorViewModel : ObservableRecipient
{
private readonly ExternalEvent _externalEvent;
private readonly ScriptRunnerHandler _scriptRunnerHandler;
[ObservableProperty]
private string _result;
private DocumentViewModel _activeDocument = null;
[ObservableProperty]
private Visibility _isRunning = Visibility.Collapsed;
public RoslynCodeEditor CodeEditor { get; set; }
public RoslynEditorViewModel(RevitRoslynHost host, ExternalEvent externalEvent, ScriptRunnerHandler scriptRunnerHandler)
{
Host = host;
scriptRunnerHandler.RoslynEditorViewModel = this;
_externalEvent = externalEvent;
_scriptRunnerHandler = scriptRunnerHandler;
IsActive = true;
WeakReferenceMessenger.Default.Register<RoslynEditorViewModel, string, string>(this, "RunScript", (r, m) => Code = m);
}
public IHighlightingDefinition HighlightingDefinition
{
get
{
//var resourceName = "YourNamespace.Resources.CustomHighlighting.xshd";
//using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
using (var stream = File.OpenRead("Dark.xshd"))
{
var reader = new XmlTextReader(stream);
return HighlightingLoader.Load(reader, HighlightingManager.Instance);
}
}
}
public RevitRoslynHost Host { get; }
ObservableCollection<DocumentViewModel> _documents = new ObservableCollection<DocumentViewModel>();
ReadOnlyObservableCollection<DocumentViewModel> _readonlydocuments = null;
public ReadOnlyObservableCollection<DocumentViewModel> Documents
{
get
{
if (_readonlydocuments == null)
_readonlydocuments = new ReadOnlyObservableCollection<DocumentViewModel>(_documents);
return _readonlydocuments;
}
}
[RelayCommand]
private void Open(object parameter)
{
var dlg = new OpenFileDialog
{
Filter = "C# 脚本文件 (*.csx)|*.csx",
RestoreDirectory = true,
InitialDirectory = Path.Combine(GlobalVariables.DirAssembly, "Samples")
};
if (dlg.ShowDialog().GetValueOrDefault())
{
var DocumentViewModel = Open(dlg.FileName);
ActiveDocument = DocumentViewModel;
}
}
public DocumentViewModel Open(string filepath)
{
var DocumentViewModel = _documents.FirstOrDefault(fm => fm.FilePath == filepath);
if (DocumentViewModel != null)
return DocumentViewModel;
DocumentViewModel = new DocumentViewModel(this, filepath);
_documents.Add(DocumentViewModel);
return DocumentViewModel;
}
[RelayCommand]
private void About()
{
TaskDialog mainDialog = new TaskDialog("关于");//对话框的名称
mainDialog.MainInstruction = "基于开源库开发的C#脚本执行工具";//对话框标题
//mainDialog.MainContent = "C#脚本参考以下两个开源库,进行调整。";//对话框的主要内容
//mainDialog.MainContent = "复制提示词提问";//对话框的主要内容
mainDialog.ExpandedContent = @"基于Autodesk Revit软件的直接执行C#脚本可用于将AI对话的代码粘贴执行";//对话框的扩展内容
var link1 = "https://github.com/sridharbaldava/Revit.ScriptCS";
var link2 = "https://github.com/kongdetuo/RevitTools";
////添加命令链接
mainDialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink1, link1);
mainDialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink2, link2);
//mainDialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink3, "复制AI提示词");
mainDialog.CommonButtons = TaskDialogCommonButtons.Ok | TaskDialogCommonButtons.Cancel;
//mainDialog.VerificationText = "不再显示该信息";
//添加文字超链接
//mainDialog.FooterText = "<a href=\"https://github.com/sridharbaldava/Revit.ScriptCS\">" + "点此处了解更多信息</a>";
var result = mainDialog.Show();
if (result == TaskDialogResult.CommandLink1)
{
System.Diagnostics.Process.Start(link1);
}
if (result == TaskDialogResult.CommandLink2)
{
System.Diagnostics.Process.Start(link2);
}
//if (result == TaskDialogResult.CommandLink3)
//{
// try
// {
// Clipboard.SetText("Revit二次开发中使用变量doc和uidoc两个变量构造一个保证可以执行的C#代码块添加相应注释不需要方法签名和using命名空间但使用时需要完整的命名空间。实现<此处填写你的需求>");
// }
// catch (Exception ex)
// {
// MessageBox.Show(ex.Message);
// }
//}
}
[RelayCommand]
private void New()
{
// _documents.Add(new DocumentViewModel(this) { Document = new TextDocument() });
_documents.Add(new DocumentViewModel(this));
ActiveDocument = _documents.Last();
}
public DocumentViewModel ActiveDocument
{
get { return _activeDocument; }
set
{
if (_activeDocument != value)
{
_activeDocument = value;
OnPropertyChanged(nameof(ActiveDocument));
ActiveDocumentChanged?.Invoke(this, EventArgs.Empty);
}
}
}
public event EventHandler ActiveDocumentChanged;
internal void Close(DocumentViewModel fileToClose)
{
if (fileToClose.IsDirty)
{
var res = MessageBox.Show(string.Format("保存文件修改 '{0}'?", fileToClose.FileName), "Revit C#脚本", MessageBoxButton.YesNoCancel);
if (res == MessageBoxResult.Cancel)
return;
if (res == MessageBoxResult.Yes)
{
Save(fileToClose);
}
}
_documents.Remove(fileToClose);
}
internal void Save(DocumentViewModel fileToSave, bool saveAsFlag = false)
{
if (fileToSave.FilePath == null || saveAsFlag)
{
var dlg = new SaveFileDialog();
dlg.Filter = "C# 脚本 (*.csx)|*.csx";
if (dlg.ShowDialog().GetValueOrDefault())
fileToSave.FilePath = dlg.FileName;
else
return;
}
File.WriteAllText(fileToSave.FilePath, fileToSave.Text);
ActiveDocument.IsDirty = false;
}
internal void Run(DocumentViewModel documentViewModel)
{
Result = string.Empty;
IsRunning = Visibility.Visible;
_scriptRunnerHandler.ScriptText = documentViewModel.Text;
_externalEvent.Raise();
}
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(RunCodeCommand))]
[NotifyCanExecuteChangedFor(nameof(CopyCodeCommand))]
private string code;
public bool HasCode => !string.IsNullOrEmpty(Code);
[RelayCommand(CanExecute = nameof(HasCode))]
internal void RunCode()
{
Result = string.Empty;
IsRunning = Visibility.Visible;
_scriptRunnerHandler.ScriptText = Code;
_externalEvent.Raise();
}
[RelayCommand(CanExecute = nameof(HasCode))]
internal void CopyCode()
{
Clipboard.SetText(Code);
}
}
}

View File

@@ -0,0 +1,23 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
namespace Szmedi.RvKits.RvScript
{
public class ScriptGlobals
{
public Document doc;
public UIDocument uidoc;
private readonly IProgress<string> progress;
public ScriptGlobals(IProgress<string> Progress)
{
progress = Progress;
}
public void Print(string Message)
{
progress.Report(Message);
}
}
}

View File

@@ -0,0 +1,196 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Threading;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Nice3point.Revit.Toolkit.External;
using RoslynPad.Roslyn;
using Szmedi.RvKits.Assists;
namespace Szmedi.RvKits.RvScript
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class ScriptRunnerCmd : IExternalCommand
{
//public override void Execute()
//{
// if (WinIntPtr.IsVisible("C#脚本执行"))
// {
// WinIntPtr.ShowAndActive("C#脚本执行");
// }
// else
// {
// try
// {
// ShowNoModel();
// }
// catch (Exception ex)
// {
// MessageBox.Show(ex.ToString(), "错误");
// }
// }
//}
private void ShowNoModel()
{
var handler = new ScriptRunnerHandler();
var externalEvent = ExternalEvent.Create(handler);
var assembliesToRef = new List<Assembly>
{
typeof(object).Assembly, //mscorlib
//typeof(Uri).Assembly, // System
//typeof(Enumerable).Assembly, // System.Core
//Assembly.Load("Microsoft.CodeAnalysis.Workspaces"),
//Assembly.Load("System.Numerics.Vectors"),
typeof(UIApplication).Assembly,
typeof(Document).Assembly,
Assembly.Load("RoslynPad.Roslyn.Windows"),
Assembly.Load("RoslynPad.Editor.Windows"),
};
var roslynHost = new RevitRoslynHost(
assembliesToRef,
RoslynHostReferences.NamespaceDefault
.With(
typeNamespaceImports: new[]
{
typeof(UIApplication),
typeof(Document),
typeof(Dictionary<,>),
typeof(Enumerable),
typeof(ScriptGlobals)
}),
ImmutableArray.Create("CS1701", "CS1702", "CS0518"));
var document = new RoslynEditorViewModel(roslynHost, externalEvent, handler);
try
{
var scriptEditor = new RoslynEditor(document)
{
WindowStartupLocation = WindowStartupLocation.CenterScreen
};
_ = new WindowInteropHelper(scriptEditor) { Owner = Process.GetCurrentProcess().MainWindowHandle };
handler.Progress = new Progress<string>(message => document.Result += $"{message}{Environment.NewLine}");
scriptEditor.Show();
}
catch (Exception ex)
{
MessageBox.Show($"{ex.Message}\r\n{ex.StackTrace}");
}
finally
{
//因为是非模态窗口,所以会直接执行取消订阅。
//如果运行过程中会报错,会导致在运行过程中出现未加载程序集时,
//无法加载程序集,需要在窗口关闭后才执行移除订阅
//AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
}
}
public static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
//Assembly.Load("System.Runtime.CompilerServices.Unsafe");
var dllName = args.Name.Split(',')[0];
Debug.WriteLine(dllName);
//Directory.GetFiles(GlobalVariables.DirAssembly, "*.dll", SearchOption.AllDirectories).ToList().ForEach(f =>
// {
// if (Path.GetFileNameWithoutExtension(f) == dllName)
// {
// Assembly.LoadFrom(f);
// }
// });
var collection = Directory.GetFiles(GlobalVariables.DirAssembly, "*.dll", SearchOption.AllDirectories);
foreach (var f in collection)
{
if (Path.GetFileNameWithoutExtension(f) == dllName)
{
return Assembly.LoadFrom(f);
}
}
return null;
//Directory.GetFiles(GlobalVariables.DirAssembly, "*.dll", SearchOption.AllDirectories).ToList().ForEach(f =>
// {
// if (Path.GetFileNameWithoutExtension(f) == dllName)
// {
// Assembly.LoadFrom(f);
// }
// });
//foreach (var f in collection)
//{
// if (Path.GetFileNameWithoutExtension(f) == dllName)
// {
// return Assembly.LoadFrom(f);
// }
//}
//return null;
//if (args.Name.StartsWith("AvalonDock.resources"))
//{
// string resourcePath = Path.Combine(GlobalVariables.DirAssembly, "zh-Hans", "AvalonDock.resources.dll");
// return File.Exists(resourcePath) ? Assembly.LoadFrom(resourcePath) : null;
//}
//if (args.Name.StartsWith("AvalonDock"))
//{
// string assemblyFile = Path.Combine(GlobalVariables.DirAssembly, "AvalonDock.dll");
// return File.Exists(assemblyFile) ? Assembly.LoadFrom(assemblyFile) : null;
//}
//var collection = new List<string>
//{
// "System.Memory",
// "System.Runtime.CompilerServices.Unsafe",
// "System.Numerics.Vectors",
//};
//foreach (var item in collection)
//{
// string services = Path.Combine(GlobalVariables.DirAssembly, $"{item}.dll");
// Assembly.LoadFrom(services);
//}
//string services = Path.Combine(GlobalVariables.DirAssembly, "System.Memory.dll");
//if (File.Exists(services))
//{
// Assembly.LoadFrom(services);
//}
//var dll = Directory.GetFiles(GlobalVariables.DirAssembly, "*.dll")
// .Where(f => Path.GetFileNameWithoutExtension(f) == dllName).FirstOrDefault();
//return File.Exists(dll) ? Assembly.LoadFrom(dll) : null;
}
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
if (WinIntPtr.IsVisible("C#脚本执行"))
{
WinIntPtr.ShowAndActive("C#脚本执行");
}
else
{
try
{
ShowNoModel();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "错误");
}
}
return Result.Succeeded;
}
}
}

View File

@@ -0,0 +1,94 @@
using System.Reflection;
using Autodesk.Revit.UI;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.CSharp.Scripting.Hosting;
using Microsoft.CodeAnalysis.Scripting;
namespace Szmedi.RvKits.RvScript
{
public class ScriptRunnerHandler : IExternalEventHandler
{
public string ScriptText { get; internal set; }
public string ScriptResult { get; private set; }
public RoslynEditorViewModel RoslynEditorViewModel { get; set; }
public IProgress<string> Progress { get; set; }
public void Execute(UIApplication app)
{
var assembliesToRef = new List<Assembly>
{
typeof(object).Assembly, //mscorlib
typeof(Autodesk.Revit.UI.UIApplication).Assembly, // Microsoft.CodeAnalysis.Workspaces
typeof(Autodesk.Revit.DB.Document).Assembly, // Microsoft.Build
};
var namespaces = new List<string>
{
"Autodesk.Revit.UI",
"Autodesk.Revit.DB",
"Autodesk.Revit.DB.Structure",
"System",
"Autodesk.Revit.DB.Mechanical",
"System.Collections.Generic",
"Autodesk.Revit.DB.Plumbing",
"Autodesk.Revit.DB.Electrical",
"System.IO",
"System.Linq"
};
ScriptGlobals globals = new ScriptGlobals(Progress) { doc = app.ActiveUIDocument.Document, uidoc = app.ActiveUIDocument };
var options = ScriptOptions.Default.AddReferences(assembliesToRef).WithImports(namespaces);
//AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
try
{
object result = CSharpScript.EvaluateAsync<object>(ScriptText, options, globals).Result;
if (!(result is null))
RoslynEditorViewModel.Result += CSharpObjectFormatter.Instance.FormatObject(result) + Environment.NewLine;
RoslynEditorViewModel.IsRunning = System.Windows.Visibility.Collapsed;
}
catch (AggregateException AggEx)
{
AggEx.Handle(ex =>
{
RoslynEditorViewModel.Result += $"{CSharpObjectFormatter.Instance.FormatObject(ex)}{Environment.NewLine}";
return true;
}
);
RoslynEditorViewModel.IsRunning = System.Windows.Visibility.Collapsed;
}
catch (System.Exception ex)
{
RoslynEditorViewModel.Result += CSharpObjectFormatter.Instance.FormatObject(ex) + Environment.NewLine;
RoslynEditorViewModel.IsRunning = System.Windows.Visibility.Collapsed;
}
finally
{
RoslynEditorViewModel.IsRunning = System.Windows.Visibility.Collapsed;
//AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
}
}
//private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
//{
// if (args.Name.StartsWith("System.Runtime.CompilerServices.Unsafe"))
// {
// string services = Path.Combine(GlobalVariables.DirAssembly, "System.Runtime.CompilerServices.Unsafe.dll");
// if (File.Exists(services))
// {
// return Assembly.LoadFrom(services);
// }
// }
// return null;
//}
public string GetName()
{
return "执行脚本";
}
}
}