diff --git a/NeoUI/NeoUI/Appearance/ThemeManager.cs b/NeoUI/NeoUI/Appearance/ThemeManager.cs index f4a9e54..ad1129f 100644 --- a/NeoUI/NeoUI/Appearance/ThemeManager.cs +++ b/NeoUI/NeoUI/Appearance/ThemeManager.cs @@ -86,7 +86,7 @@ namespace NeoUI.Appearance { foreach (var key in dict.Keys.OfType()) { - if (dict[key] is SolidColorBrush && key != null) + if (dict[key] is SolidColorBrush) keys.Add(key.ToString()); } } diff --git a/NeoUI/NeoUI/Controls/Breadcrumb.xaml.cs b/NeoUI/NeoUI/Controls/Breadcrumb.xaml.cs index 41d6563..33f5c10 100644 --- a/NeoUI/NeoUI/Controls/Breadcrumb.xaml.cs +++ b/NeoUI/NeoUI/Controls/Breadcrumb.xaml.cs @@ -118,17 +118,18 @@ public class Breadcrumb : ItemsControl { base.OnItemsChanged(e); - if(e.OldItems is { }) + if (e.OldItems is null) return; + if (e.NewItems != null) { - foreach(var item in e.NewItems.OfType()) + foreach (var item in e.NewItems.OfType()) { item.Navigate += BreadcrumbItem_Navigate; } + } - foreach(var item in e.OldItems.OfType()) - { - item.Navigate -= BreadcrumbItem_Navigate; - } + foreach(var item in e.OldItems.OfType()) + { + item.Navigate -= BreadcrumbItem_Navigate; } } diff --git a/NeoUI/NeoUI/Controls/ColorPicker/ColorPanel.xaml.cs b/NeoUI/NeoUI/Controls/ColorPicker/ColorPanel.xaml.cs index 80e6e58..f5ca946 100644 --- a/NeoUI/NeoUI/Controls/ColorPicker/ColorPanel.xaml.cs +++ b/NeoUI/NeoUI/Controls/ColorPicker/ColorPanel.xaml.cs @@ -237,8 +237,8 @@ public class ColorPanel : Control public override void OnApplyTemplate() { base.OnApplyTemplate(); - colorCanvas = (Canvas)GetTemplateChild("PART_ColorCanvas"); - colorSelector = (Thumb)GetTemplateChild("PART_ColorSelector"); + colorCanvas = (Canvas?)GetTemplateChild("PART_ColorCanvas"); + colorSelector = (Thumb?)GetTemplateChild("PART_ColorSelector"); if (colorSelector == null || colorCanvas == null) return; colorSelector.DragDelta += ColorSelector_DragDelta; colorCanvas.MouseLeftButtonDown += ColorCanvas_MouseLeftButtonDown; diff --git a/NeoUI/NeoUI/Controls/Hyperlink.xaml.cs b/NeoUI/NeoUI/Controls/Hyperlink.xaml.cs index b842e16..7eea005 100644 --- a/NeoUI/NeoUI/Controls/Hyperlink.xaml.cs +++ b/NeoUI/NeoUI/Controls/Hyperlink.xaml.cs @@ -23,7 +23,7 @@ public class Hyperlink : ButtonBase /// 定义私有的 Key:这是“写入权限”的钥匙,只有在这个类内部才能拿到 /// public static readonly DependencyProperty IsVisitedProperty = - IsVisitedPropertyKey?.DependencyProperty; + IsVisitedPropertyKey.DependencyProperty; /// /// 表示已经浏览过的依赖属性。 /// @@ -63,20 +63,18 @@ public class Hyperlink : ButtonBase { base.OnMouseLeftButtonDown(e); - if (!string.IsNullOrEmpty(NavigateUri)) + if (string.IsNullOrEmpty(NavigateUri)) return; + try { - try - { - // 1. 打开网页 - Process.Start(new ProcessStartInfo(NavigateUri) { UseShellExecute = true }); + // 1. 打开网页 + Process.Start(new ProcessStartInfo(NavigateUri) { UseShellExecute = true }); - // 2. 改变自身状态(这就是你作为控件的“记忆”) - SetValue(IsVisitedPropertyKey, true); - } - catch - { - // 忽略无效链接异常 - } + // 2. 改变自身状态(这就是你作为控件的“记忆”) + SetValue(IsVisitedPropertyKey, true); + } + catch + { + // 忽略无效链接异常 } } } diff --git a/NeoUI/NeoUI/Controls/MultiComboBox.xaml.cs b/NeoUI/NeoUI/Controls/MultiComboBox.xaml.cs index 9b40e09..5133827 100644 --- a/NeoUI/NeoUI/Controls/MultiComboBox.xaml.cs +++ b/NeoUI/NeoUI/Controls/MultiComboBox.xaml.cs @@ -610,7 +610,7 @@ public class MultiComboBox : Control else { // 优化多选同步算法,避免每次都 ToList() - var sourceList = SelectedItems as IList; + var sourceList = SelectedItems; if (sourceList == null) return; // 使用 HashSet 提高查找速度 O(1) @@ -763,7 +763,7 @@ public class MultiComboBox : Control } // 处理第一个元素 - if (IsMatch(firstItem, filter, propDesc)) filtered.Add(firstItem); + if (IsMatch(firstItem, filter!, propDesc)) filtered.Add(firstItem); } // 处理剩余元素 @@ -777,7 +777,7 @@ public class MultiComboBox : Control } // 辅助方法,内联以减少调用开销 - private bool IsMatch(object? item, string filter, PropertyDescriptor? propDesc) + private static bool IsMatch(object? item, string filter, PropertyDescriptor? propDesc) { if (item == null) return false; string? value; diff --git a/NeoUI/NeoUI/Controls/NeoWindow.xaml.cs b/NeoUI/NeoUI/Controls/NeoWindow.xaml.cs index ccdeafb..76b646d 100644 --- a/NeoUI/NeoUI/Controls/NeoWindow.xaml.cs +++ b/NeoUI/NeoUI/Controls/NeoWindow.xaml.cs @@ -197,21 +197,18 @@ public class NeoWindow : Window stateName = "Normal"; } //VisualStateManager.GoToState(maximizeRestoreButton, stateName, true); - switch (stateName) + maximizeRestoreButton?.Background = stateName switch { - case "Pressed": + "Pressed" => //VisualStateManager.GoToState(maximizeRestoreButton, "Pressed", true); - maximizeRestoreButton.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#33000000")); - break; - case "MouseOver": - maximizeRestoreButton.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#1A000000")); + new SolidColorBrush((Color)ColorConverter.ConvertFromString("#33000000")), + "MouseOver" => //VisualStateManager.GoToState(maximizeRestoreButton, "MouseOver", true); - break; - case "Normal": - maximizeRestoreButton.Background = Brushes.Transparent; + new SolidColorBrush((Color)ColorConverter.ConvertFromString("#1A000000")), + "Normal" => Brushes.Transparent, //VisualStateManager.GoToState(maximizeRestoreButton, "Normal", true); - break; - } + _ => maximizeRestoreButton?.Background + }; } #region Window Control Methods diff --git a/NeoUI/NeoUI/Markup/EnumSourceExtension.cs b/NeoUI/NeoUI/Markup/EnumSourceExtension.cs index d86d3d5..757c60a 100644 --- a/NeoUI/NeoUI/Markup/EnumSourceExtension.cs +++ b/NeoUI/NeoUI/Markup/EnumSourceExtension.cs @@ -66,36 +66,33 @@ namespace NeoUI.Markup //如果为空,则返回运行时绑定的类。 if (pvt.TargetObject is not FrameworkElement) { return this; } - if (enumType != null) + if (enumType == null) return null; + var enumValues = Enum.GetValues(enumType); + if (!BindToDescription) return enumValues; + var items = new List(); + foreach (var enumValue in enumValues) { - var enumValues = Enum.GetValues(enumType); - if (!BindToDescription) return enumValues; - var items = new List(); - foreach (var enumValue in enumValues) + var item = new { - var item = new - { - Value = enumValue, - Description = GetDescription(enumValue) - }; - items.Add(item); - } - - if (pvt.TargetObject is Selector selector) - { - selector.DisplayMemberPath = "Description"; - selector.SelectedValuePath = "Value"; - } - - return items; + Value = enumValue, + Description = GetDescription(enumValue) + }; + items.Add(item); } - return null; + if (pvt.TargetObject is Selector selector) + { + selector.DisplayMemberPath = "Description"; + selector.SelectedValuePath = "Value"; + } + + return items; + } - private static string GetDescription(object enumValue) + private static string? GetDescription(object? enumValue) { if (enumValue == null) return string.Empty; - var fieldInfo = enumValue.GetType().GetField(enumValue.ToString()); + var fieldInfo = enumValue.GetType().GetField(enumValue.ToString() ?? string.Empty); var descriptionAttribute = fieldInfo?.GetCustomAttribute(); return descriptionAttribute?.Description ?? enumValue.ToString(); diff --git a/NeoUI/NeoUI/NeoUI.csproj b/NeoUI/NeoUI/NeoUI.csproj index e61dbec..c1a88fe 100644 --- a/NeoUI/NeoUI/NeoUI.csproj +++ b/NeoUI/NeoUI/NeoUI.csproj @@ -3,7 +3,7 @@ net462;net8.0-windows enable - 13.0 + preview enable true 1.0.0 diff --git a/RevitAddin/NuGet.config b/RevitAddin/NuGet.config deleted file mode 100644 index 9e263ce..0000000 --- a/RevitAddin/NuGet.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/RevitAddin/Resources/Revit.ico b/RevitAddin/Resources/Revit.ico deleted file mode 100644 index c449401..0000000 Binary files a/RevitAddin/Resources/Revit.ico and /dev/null differ diff --git a/RevitAddin/Revit/App.cs b/RevitAddin/Revit/App.cs deleted file mode 100644 index 66e6e19..0000000 --- a/RevitAddin/Revit/App.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Reflection; -using System.Runtime.CompilerServices; -using Autodesk.Revit.DB; -using Autodesk.Revit.UI; -using ricaun.Revit.UI; - - -namespace RevitAddin.Revit -{ - [AppLoader] - public class App : IExternalApplication - { - private RibbonPanel ribbonPanel; - public Result OnStartup(UIControlledApplication application) - { - ribbonPanel = application.CreatePanel("RevitAddin"); - ribbonPanel.CreatePushButton() - .SetLargeImage("Resources/Revit.ico"); - return Result.Succeeded; - } - - public Result OnShutdown(UIControlledApplication application) - { - ribbonPanel?.Remove(); - return Result.Succeeded; - } - } - -} \ No newline at end of file diff --git a/RevitAddin/Revit/Commands/Command.cs b/RevitAddin/Revit/Commands/Command.cs deleted file mode 100644 index 3438098..0000000 --- a/RevitAddin/Revit/Commands/Command.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Reflection; -using Autodesk.Revit.Attributes; -using Autodesk.Revit.DB; -using Autodesk.Revit.UI; - -namespace RevitAddin.Revit.Commands -{ - [Transaction(TransactionMode.Manual)] - public class Command : IExternalCommand - { - public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet) - { - UIApplication uiapp = commandData.Application; - - System.Windows.MessageBox.Show(uiapp.Application.VersionName); - - return Result.Succeeded; - } - } -} diff --git a/RevitAddin/RevitAddin.csproj b/RevitAddin/RevitAddin.csproj deleted file mode 100644 index 9c5fc03..0000000 --- a/RevitAddin/RevitAddin.csproj +++ /dev/null @@ -1,164 +0,0 @@ - - - - - Library - AnyCPU - true - latest - false - None - - Debug 2020; 2020; - Debug 2019; 2019; - - - - - - - - 2019 - net47 - - - - - 2020 - net47 - - - - - 2021 - net48 - - - - - 2022 - net48 - - - - - 2023 - net48 - - - - - 2024 - net48 - - - - - 2025 - net8.0-windows - - - - - 2019 - net47 - - - - - - - true - true - false - - - - - true - bin\Release\$(RevitVersion) - $(DefineConstants);REVIT$(RevitVersion) - MSB3052 - None - - - - - true - bin\Debug\ - $(DefineConstants);DEBUG;TRACE;REVIT$(RevitVersion) - Full - - - - - $(RevitVersion) - Program - C:\Program Files\Autodesk\Revit $(DebugRevitVersion)\Revit.exe - - - - SolutionTemplates - 1.0.0 - - - - - - - false - $([MSBuild]::Divide($([System.DateTime]::Now.TimeOfDay.TotalSeconds), 4).ToString('F0')) - .Dev.$(Version).$(Revision) - - - - Company - Authors - Revit Plugin Description for $(PackageId). - $([System.DateTime]::Now.ToString('yyyy')) - - - - $(PackageId)$(PackageAssemblyVersion) - $(PackageId) - Copyright © $(CopyrightYears) $(Company) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Always - - - - \ No newline at end of file diff --git a/RevitAddin/bitmono.json b/RevitAddin/bitmono.json deleted file mode 100644 index fad979e..0000000 --- a/RevitAddin/bitmono.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Protections": { - "AntiDe4dot": { "Enabled": true }, - "StringsEncryption": { "Enabled": true }, // 保护敏感字符串 - "BitDotNet": { "Enabled": true }, // 防止简单的反编译 - "ControlFlow": { "Enabled": true }, // 打乱代码逻辑(重要) - "FullRenaming": { "Enabled": false } // 关闭全局重命名,避免 Revit/WPF 崩溃 - } -} \ No newline at end of file diff --git a/RevitLess/App.xaml b/RevitLess/App.xaml new file mode 100644 index 0000000..5b98c4c --- /dev/null +++ b/RevitLess/App.xaml @@ -0,0 +1,5 @@ + diff --git a/WebUITest/App.xaml.cs b/RevitLess/App.xaml.cs similarity index 93% rename from WebUITest/App.xaml.cs rename to RevitLess/App.xaml.cs index d94725d..165c8a3 100644 --- a/WebUITest/App.xaml.cs +++ b/RevitLess/App.xaml.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Threading.Tasks; using System.Windows; -namespace WebUITest +namespace RevitLess { /// /// App.xaml 的交互逻辑 diff --git a/RevitLess/BasicFileInfo.cs b/RevitLess/BasicFileInfo.cs index 867844e..6212cc4 100644 --- a/RevitLess/BasicFileInfo.cs +++ b/RevitLess/BasicFileInfo.cs @@ -8,424 +8,419 @@ using System.Text; namespace RevitLess { - public class BasicFileInfo : StorageStreamBase + public class BasicFileInfo : StorageStreamBase { - #region Private Variables + #region Private Variables - private WorkSharingMode _workSharing = WorkSharingMode.Unknown; - private string _userName = string.Empty; - private string _centralFilePath = string.Empty; - private string _revitBuild = string.Empty; - private string _lastSavedpath = string.Empty; - private int _openWorksetDefault = 0; + private WorkSharingMode workSharing = WorkSharingMode.Unknown; + private string userName = string.Empty; + private string centralFilePath = string.Empty; + private string revitBuild = string.Empty; + private string lastSavedpath = string.Empty; + private int openWorksetDefault = 0; - #endregion + #endregion - #region Constructors + #region Constructors - public BasicFileInfo(string fileName, StorageInfo storage) - : base(fileName, storage) - { - ReadStructuredStorageFile(); - } - - #endregion - - #region Public Properties - - public bool IsCentralFile - { - get - { - if((WorkSharing == WorkSharingMode.NotEnabled) || - (WorkSharing == WorkSharingMode.Unknown)) - { - return false; - } - bool fileNamesMatch = false; - bool workSharing = WorkSharing == WorkSharingMode.Central; - string fileName = Path.GetFileName(FileName).ToUpper(); - string centralFile = string.Empty; - if(CentralFilePath.Length > 0) - { - centralFile = Path.GetFileName(CentralFilePath).ToUpper(); - } - if(centralFile.Length > 0) - { - fileNamesMatch = centralFile.Equals(fileName); - } - return workSharing && fileNamesMatch; - } - } - - public bool IsLocalWorkingFile - { - get - { - if((WorkSharing == WorkSharingMode.NotEnabled) || - (WorkSharing == WorkSharingMode.Unknown)) - { - return false; - } - bool fileNamesMatch = false; - bool workSharing = WorkSharing == WorkSharingMode.Local; - string fileName = Path.GetFileName(FileName).ToUpper(); - string centralFile = string.Empty; - if(CentralFilePath.Length > 0) - { - centralFile = Path.GetFileName(CentralFilePath).ToUpper(); - } - if(centralFile.Length > 0) - { - fileNamesMatch = centralFile.Equals(fileName); - } - return workSharing || (fileNamesMatch == false); - } - } - - public WorkSharingMode WorkSharing - { - get - { - return _workSharing; - } - private set - { - _workSharing = value; - } - } - - public string UserName - { - get - { - return _userName; - } - private set - { - _userName = value; - } - } - - public string CentralFilePath - { - get - { - return _centralFilePath; - } - private set - { - _centralFilePath = value; - } - } - - public string RevitBuild - { - get - { - return _revitBuild; - } - private set - { - _revitBuild = value; - } - } - - public ProductType Product - { - get - { - if(string.IsNullOrEmpty(RevitBuild)) - { - return ProductType.Unknown; - } - - if(RevitBuild.ToUpper().IndexOf("MEP") >= 0) - { - return ProductType.MEP; - } - - if(RevitBuild.ToUpper().IndexOf("ARCHITECTURE") >= 0) - { - return ProductType.Architecture; - } - - if(RevitBuild.ToUpper().IndexOf("STRUCTURE") >= 0) - { - return ProductType.Structure; - } - - return ProductType.Unknown; - } - } - - public string BuildTimeStamp - { - get - { - if(string.IsNullOrEmpty(RevitBuild)) - { - return string.Empty; - } - - string[] buildParts = RevitBuild.Split(new char[] { ':' }); - if(buildParts != null) - { - if(buildParts.Length == 2) - { - string timeStamp = buildParts[1].Trim().Replace("(x64))", string.Empty); - timeStamp = timeStamp.Replace("(x64)", string.Empty); - timeStamp = timeStamp.Replace(")", string.Empty); - return timeStamp.Trim(); - } - } - - return _revitBuild.Trim(); - } - } - - public PlatformType Platform - { - get - { - if(string.IsNullOrEmpty(RevitBuild)) - { - return PlatformType.Unknown; - } - - if(RevitBuild.ToUpper().IndexOf("X64") >= 0) - { - return PlatformType.x64; - } - - return PlatformType.x86; - } - } - - public string LastSavedpath - { - get - { - return _lastSavedpath; - } - private set - { - _lastSavedpath = value; - } - } - - public int OpenWorksetDefault - { - get - { - return _openWorksetDefault; - } - private set - { - _openWorksetDefault = value; - } - } - - #endregion - - #region Private Properties - - - #endregion - - #region Public Methods - - - #endregion - - #region Private Methods - - private void ParseDetailInfo(string detailInfo) - { - detailInfo = detailInfo.Trim(); - int index = detailInfo.IndexOf(":"); - string detailValue = detailInfo.Substring(detailInfo.IndexOf(":") + 1); - string detailKey = detailInfo.Substring(0, detailInfo.IndexOf(":")); - detailKey = detailKey.Trim().ToUpper().Replace(" ", string.Empty); - detailKey = StringUtility.PurgeUnprintableCharacters(detailKey); - detailValue = StringUtility.PurgeUnprintableCharacters(detailValue); - - switch(detailKey) - { - case "WORKSHARING": - if(string.IsNullOrEmpty(detailValue)) - { - WorkSharing = WorkSharingMode.Unknown; - return; - } - - string workSharing = detailValue.Replace(" ", string.Empty).Trim().ToUpper(); - switch(workSharing) - { - case "NOTENABLED": - WorkSharing = WorkSharingMode.NotEnabled; - break; - - case "LOCAL": - WorkSharing = WorkSharingMode.Local; - break; - - case "CENTRAL": - WorkSharing = WorkSharingMode.Central; - break; - - default: - WorkSharing = WorkSharingMode.Unknown; - break; - } - break; - - case "USERNAME": - UserName = detailValue.Trim(); - break; - - case "CENTRALFILEPATH": - CentralFilePath = detailValue.Trim(); - break; - - case "REVITBUILD": - RevitBuild = detailValue.Trim(); - break; - - case "LASTSAVEPATH": - LastSavedpath = detailValue.Trim(); - break; - - case "OPENWORKSETDEFAULT": - OpenWorksetDefault = Convert.ToInt32(detailValue.Trim()); - break; - - default: - //Debug.Assert(false, string.Format("{0} was not found in the case tests.", detailKey)); - break; - } - } - - #endregion - - #region Protected Methods - - //internal override void ReadStructuredStorageFile() - //{ - // if(IsInitialized) - // { - // return; - // } - // try - // { - // StreamInfo[] streams = Storage.GetStreams(); - // foreach(StreamInfo stream in streams) - // { - // if(stream.Name.ToUpper().Equals("BASICFILEINFO")) - // { - // string unicodeData = StringUtility.ConvertStreamBytesToUnicode(stream); - // string[] basicFileInfoParts = unicodeData.Split(new char[] { '\0' }); - - // foreach(string basicFileInfoPart in basicFileInfoParts) - // { - // if(basicFileInfoPart.IndexOf("\r\n") >= 0) - // { - // string[] detailInfoParts = basicFileInfoPart.Split(new string[] { "\r\n" }, new StringSplitOptions()); - // foreach(string detailPart in detailInfoParts) - // { - // ParseDetailInfo(detailPart); - // } - // } - // } - // } - // } - // } - // catch(Exception ex) - // { - // LogManager.LogMessage(ex); - // IsInitialized = false; - // } - // IsInitialized = true; - //} - - public void ReadStructuredStorageFile() - { - if(IsInitialized) - { - return; - } - try - { - StreamInfo[] streams = Storage.GetStreams(); - foreach(StreamInfo stream in streams) - { - if(stream.Name.ToUpper().Equals("BASICFILEINFO")) - { - string unicodeData = StringUtility.ConvertStreamBytesToUnicode(stream); - string[] basicFileInfoParts = unicodeData.Split(new char[] { '\0' }); - - foreach(string basicFileInfoPart in basicFileInfoParts) - { - if(basicFileInfoPart.IndexOf("\r\n") >= 0) - { - string[] detailInfoParts = basicFileInfoPart.Split(new string[] { "\r\n" }, new StringSplitOptions()); - foreach(string detailPart in detailInfoParts) + public BasicFileInfo(string fileName, StorageInfo storage) + : base(fileName, storage) { - ParseDetailInfo(detailPart); + ReadStructuredStorageFile(); } - } - } - } - } - } - catch(Exception ex) - { - Debug.WriteLine(ex.Message); - IsInitialized = false; - } - IsInitialized = true; - } - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - string seperator = string.Empty; - try - { - if(this != null) - { - seperator = "+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+" + Environment.NewLine; - sb.Append(string.Format("FileName: <{0}>{1}", FileName, Environment.NewLine)); - sb.Append(seperator); - sb.Append(string.Format("BasicFileInfo Section{0}", Environment.NewLine)); - sb.Append(seperator); - sb.Append(string.Format("DocType: <{0}>{1}", DocType, Environment.NewLine)); - sb.Append(string.Format("WorkSharing: <{0}>{1}", WorkSharing, Environment.NewLine)); - sb.Append(string.Format("IsCentralFile: <{0}>{1}", IsCentralFile, Environment.NewLine)); - sb.Append(string.Format("UserName: <{0}>{1}", UserName, Environment.NewLine)); - sb.Append(string.Format("CentralFilePath: <{0}>{1}", CentralFilePath, Environment.NewLine)); - sb.Append(string.Format("RevitBuild: <{0}>{1}", RevitBuild, Environment.NewLine)); - sb.Append(string.Format("Product: <{0}>{1}", Product, Environment.NewLine)); - sb.Append(string.Format("Platform: <{0}>{1}", Platform, Environment.NewLine)); - sb.Append(string.Format("BuildTimeStamp: <{0}>{1}", BuildTimeStamp, Environment.NewLine)); - sb.Append(string.Format("LastSavedpath: <{0}>{1}", LastSavedpath, Environment.NewLine)); - sb.Append(string.Format("OpenWorksetDefault: <{0}>{1}", OpenWorksetDefault, Environment.NewLine)); - sb.Append(seperator); - seperator = sb.ToString(); - return seperator; - } - } - finally - { - sb.Length = 0; - sb.Capacity = 0; - sb = null; - } - return string.Empty; - } + #endregion - #endregion - } + #region Public Properties + + public bool IsCentralFile + { + get + { + if ((WorkSharing == WorkSharingMode.NotEnabled) || + (WorkSharing == WorkSharingMode.Unknown)) + { + return false; + } + bool fileNamesMatch = false; + bool workSharing = WorkSharing == WorkSharingMode.Central; + string fileName = Path.GetFileName(FileName).ToUpper(); + string centralFile = string.Empty; + if (CentralFilePath.Length > 0) + { + centralFile = Path.GetFileName(CentralFilePath).ToUpper(); + } + if (centralFile.Length > 0) + { + fileNamesMatch = centralFile.Equals(fileName); + } + return workSharing && fileNamesMatch; + } + } + + public bool IsLocalWorkingFile + { + get + { + if ((WorkSharing == WorkSharingMode.NotEnabled) || + (WorkSharing == WorkSharingMode.Unknown)) + { + return false; + } + bool fileNamesMatch = false; + bool workSharing = WorkSharing == WorkSharingMode.Local; + string fileName = Path.GetFileName(FileName).ToUpper(); + string centralFile = string.Empty; + if (CentralFilePath.Length > 0) + { + centralFile = Path.GetFileName(CentralFilePath).ToUpper(); + } + if (centralFile.Length > 0) + { + fileNamesMatch = centralFile.Equals(fileName); + } + return workSharing || (fileNamesMatch == false); + } + } + + public WorkSharingMode WorkSharing + { + get + { + return workSharing; + } + private set + { + workSharing = value; + } + } + + public string UserName + { + get + { + return userName; + } + private set + { + userName = value; + } + } + + public string CentralFilePath + { + get + { + return centralFilePath; + } + private set + { + centralFilePath = value; + } + } + + public string RevitBuild + { + get + { + return revitBuild; + } + private set + { + revitBuild = value; + } + } + + public ProductType Product + { + get + { + if (string.IsNullOrEmpty(RevitBuild)) + { + return ProductType.Unknown; + } + + if (RevitBuild.ToUpper().IndexOf("MEP") >= 0) + { + return ProductType.MEP; + } + + if (RevitBuild.ToUpper().IndexOf("ARCHITECTURE") >= 0) + { + return ProductType.Architecture; + } + + if (RevitBuild.ToUpper().IndexOf("STRUCTURE") >= 0) + { + return ProductType.Structure; + } + + return ProductType.Unknown; + } + } + + public string BuildTimeStamp + { + get + { + if (string.IsNullOrEmpty(RevitBuild)) + { + return string.Empty; + } + + string[] buildParts = RevitBuild.Split(new char[] { ':' }); + if (buildParts != null) + { + if (buildParts.Length == 2) + { + string timeStamp = buildParts[1].Trim().Replace("(x64))", string.Empty); + timeStamp = timeStamp.Replace("(x64)", string.Empty); + timeStamp = timeStamp.Replace(")", string.Empty); + return timeStamp.Trim(); + } + } + + return revitBuild.Trim(); + } + } + + public PlatformType Platform + { + get + { + if (string.IsNullOrEmpty(RevitBuild)) + { + return PlatformType.Unknown; + } + + if (RevitBuild.ToUpper().IndexOf("X64") >= 0) + { + return PlatformType.X64; + } + + return PlatformType.X86; + } + } + + public string LastSavedpath + { + get + { + return lastSavedpath; + } + private set + { + lastSavedpath = value; + } + } + + public int OpenWorksetDefault + { + get + { + return openWorksetDefault; + } + private set + { + openWorksetDefault = value; + } + } + + #endregion + + #region Public Methods + + + #endregion + + #region Private Methods + + private void ParseDetailInfo(string detailInfo) + { + detailInfo = detailInfo.Trim(); + int index = detailInfo.IndexOf(":"); + string detailValue = detailInfo.Substring(detailInfo.IndexOf(":") + 1); + string detailKey = detailInfo.Substring(0, detailInfo.IndexOf(":")); + detailKey = detailKey.Trim().ToUpper().Replace(" ", string.Empty); + detailKey = StringUtility.PurgeUnprintableCharacters(detailKey); + detailValue = StringUtility.PurgeUnprintableCharacters(detailValue); + + switch (detailKey) + { + case "WORKSHARING": + if (string.IsNullOrEmpty(detailValue)) + { + WorkSharing = WorkSharingMode.Unknown; + return; + } + + string workSharing = detailValue.Replace(" ", string.Empty).Trim().ToUpper(); + switch (workSharing) + { + case "NOTENABLED": + WorkSharing = WorkSharingMode.NotEnabled; + break; + + case "LOCAL": + WorkSharing = WorkSharingMode.Local; + break; + + case "CENTRAL": + WorkSharing = WorkSharingMode.Central; + break; + + default: + WorkSharing = WorkSharingMode.Unknown; + break; + } + break; + + case "USERNAME": + UserName = detailValue.Trim(); + break; + + case "CENTRALFILEPATH": + CentralFilePath = detailValue.Trim(); + break; + + case "REVITBUILD": + RevitBuild = detailValue.Trim(); + break; + + case "LASTSAVEPATH": + LastSavedpath = detailValue.Trim(); + break; + + case "OPENWORKSETDEFAULT": + OpenWorksetDefault = Convert.ToInt32(detailValue.Trim()); + break; + + default: + //Debug.Assert(false, string.Format("{0} was not found in the case tests.", detailKey)); + break; + } + } + + #endregion + + #region Protected Methods + + //internal override void ReadStructuredStorageFile() + //{ + // if(IsInitialized) + // { + // return; + // } + // try + // { + // StreamInfo[] streams = Storage.GetStreams(); + // foreach(StreamInfo stream in streams) + // { + // if(stream.Name.ToUpper().Equals("BASICFILEINFO")) + // { + // string unicodeData = StringUtility.ConvertStreamBytesToUnicode(stream); + // string[] basicFileInfoParts = unicodeData.Split(new char[] { '\0' }); + + // foreach(string basicFileInfoPart in basicFileInfoParts) + // { + // if(basicFileInfoPart.IndexOf("\r\n") >= 0) + // { + // string[] detailInfoParts = basicFileInfoPart.Split(new string[] { "\r\n" }, new StringSplitOptions()); + // foreach(string detailPart in detailInfoParts) + // { + // ParseDetailInfo(detailPart); + // } + // } + // } + // } + // } + // } + // catch(Exception ex) + // { + // LogManager.LogMessage(ex); + // IsInitialized = false; + // } + // IsInitialized = true; + //} + + public void ReadStructuredStorageFile() + { + if (IsInitialized) + { + return; + } + try + { + StreamInfo[] streams = Storage.GetStreams(); + foreach (StreamInfo stream in streams) + { + if (stream.Name.ToUpper().Equals("BASICFILEINFO")) + { + string unicodeData = StringUtility.ConvertStreamBytesToUnicode(stream); + string[] basicFileInfoParts = unicodeData.Split(new char[] { '\0' }); + + foreach (string basicFileInfoPart in basicFileInfoParts) + { + if (basicFileInfoPart.IndexOf("\r\n") >= 0) + { + string[] detailInfoParts = basicFileInfoPart.Split(new string[] { "\r\n" }, new StringSplitOptions()); + foreach (string detailPart in detailInfoParts) + { + ParseDetailInfo(detailPart); + } + } + } + } + } + } + catch (Exception ex) + { + Debug.WriteLine(ex.Message); + IsInitialized = false; + } + IsInitialized = true; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + string seperator = string.Empty; + try + { + if (this != null) + { + seperator = "+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+" + Environment.NewLine; + sb.Append(string.Format("FileName: <{0}>{1}", FileName, Environment.NewLine)); + sb.Append(seperator); + sb.Append(string.Format("BasicFileInfo Section{0}", Environment.NewLine)); + sb.Append(seperator); + sb.Append(string.Format("DocType: <{0}>{1}", DocType, Environment.NewLine)); + sb.Append(string.Format("WorkSharing: <{0}>{1}", WorkSharing, Environment.NewLine)); + sb.Append(string.Format("IsCentralFile: <{0}>{1}", IsCentralFile, Environment.NewLine)); + sb.Append(string.Format("UserName: <{0}>{1}", UserName, Environment.NewLine)); + sb.Append(string.Format("CentralFilePath: <{0}>{1}", CentralFilePath, Environment.NewLine)); + sb.Append(string.Format("RevitBuild: <{0}>{1}", RevitBuild, Environment.NewLine)); + sb.Append(string.Format("Product: <{0}>{1}", Product, Environment.NewLine)); + sb.Append(string.Format("Platform: <{0}>{1}", Platform, Environment.NewLine)); + sb.Append(string.Format("BuildTimeStamp: <{0}>{1}", BuildTimeStamp, Environment.NewLine)); + sb.Append(string.Format("LastSavedpath: <{0}>{1}", LastSavedpath, Environment.NewLine)); + sb.Append(string.Format("OpenWorksetDefault: <{0}>{1}", OpenWorksetDefault, Environment.NewLine)); + sb.Append(seperator); + seperator = sb.ToString(); + return seperator; + } + } + finally + { + sb.Length = 0; + sb.Capacity = 0; + sb = null; + } + return string.Empty; + } + + #endregion + } } diff --git a/RevitLess/MainViewModel.cs b/RevitLess/MainViewModel.cs new file mode 100644 index 0000000..f805796 --- /dev/null +++ b/RevitLess/MainViewModel.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Windows; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Microsoft.Win32; +using System.Runtime.InteropServices; +using System.Windows.Interop; +using System.Windows.Media.Imaging; + +namespace RevitLess +{ + public partial class MainViewModel : ObservableObject + { + [ObservableProperty] + public partial List SymbolTypes { get; set; } + [ObservableProperty] + public partial RevitFileAssist.FamilyTypeDefinition SelectedSymbolType { get; set; } + [ObservableProperty] + public partial System.Windows.Media.ImageSource PreviewImage { get; set; } + + [ObservableProperty] + public partial string FileInfo { get; set; } + + [DllImport("gdi32.dll")] + static extern bool DeleteObject(IntPtr hObject); + + public static System.Windows.Media.ImageSource ToImageSource(System.Drawing.Image image) + { + if (image == null) + { + return null; + } + + // 始终创建一个与输入 image 无关的 Bitmap 副本(深拷贝), + // 然后从该副本获取 HBITMAP 并创建 WPF BitmapSource。 + // 这样可以确保底层 GDI+ 资源在返回后仍然有效(WPF 会复制像素数据)。 + using (System.Drawing.Bitmap clone = new System.Drawing.Bitmap(image)) + { + IntPtr hBitmap = clone.GetHbitmap(); + try + { + System.Windows.Media.Imaging.BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap( + hBitmap, + IntPtr.Zero, + Int32Rect.Empty, + BitmapSizeOptions.FromEmptyOptions()); + bitmapSource.Freeze(); + return bitmapSource; + } + finally + { + // 释放由 GetHbitmap 创建的 GDI 对象 + DeleteObject(hBitmap); + } + } + } + + private static System.Windows.Media.ImageSource ConvertImageToImageSource(System.Drawing.Image image) + { + using (var ms = new MemoryStream()) + { + image.Save(ms, ImageFormat.Png); + ms.Seek(0, SeekOrigin.Begin); + var bitmap = new System.Windows.Media.Imaging.BitmapImage(); + bitmap.BeginInit(); + bitmap.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad; + bitmap.StreamSource = ms; + bitmap.EndInit(); + bitmap.Freeze(); + return bitmap; + } + } + [RelayCommand] + private void OpenFile() + { + OpenFileDialog dialog = new OpenFileDialog(); + dialog.Filter = "Revit文件|*.rvt;*.rfa"; + if (dialog.ShowDialog() == true) + { + Storage storage = new Storage(dialog.FileName); + //var image = storage.ThumbnailImage.GetPreviewAsImage(); + var info = new RevitFileAssist(dialog.FileName); + PreviewImage = ToImageSource(info.PreviewImage); + SymbolTypes = info.SymbolTypes; + //FileInfo = info.FileInfo.ToString(); + //FileInfo = storage.BasicInfo.ToString(); + //SaveImage(dialog.FileName); + } + } + private static void SaveImage(string filePath) + { + var fi = new System.IO.FileInfo(filePath); + Storage storage = new Storage(fi.FullName); + var b = storage.ThumbnailImage.GetPreviewAsImage(); + MessageBox.Show(storage.BasicInfo.ToString()); + + //Bitmap bm = new Bitmap(b.Width, b.Height, PixelFormat.Format24bppRgb); + //Graphics g = Graphics.FromImage(bm); + //g.DrawImage(b, new Point(0, 0)); + //g.Dispose(); + + //bm.Save(Path.Combine(fi.Directory.FullName, "_Images", fi.Name.Remove(fi.Name.Length - 4) + ".png"), System.Drawing.Imaging.ImageFormat.Png); + } + } + +} \ No newline at end of file diff --git a/RevitLess/MainWindow.xaml b/RevitLess/MainWindow.xaml new file mode 100644 index 0000000..192ffff --- /dev/null +++ b/RevitLess/MainWindow.xaml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - \ No newline at end of file diff --git a/WPFUI.Test/ChatFunction/ChatDialogue.xaml.cs b/WPFUI.Test/ChatFunction/ChatDialogue.xaml.cs deleted file mode 100644 index a014d0d..0000000 --- a/WPFUI.Test/ChatFunction/ChatDialogue.xaml.cs +++ /dev/null @@ -1,218 +0,0 @@ -using System.Diagnostics; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; - -namespace WPFUI.Test -{ - /// - /// ChatDialogue.xaml 的交互逻辑 - /// - public partial class ChatDialogue - { - private ChatDialogueViewModel viewModel = new ChatDialogueViewModel(); - public ChatDialogue() - { - InitializeComponent(); - this.DataContext = viewModel; - } - - private void OpenHyperlink(object sender, ExecutedRoutedEventArgs e) - { - Process.Start(e.Parameter.ToString()); - } - - private void ClickOnImage(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) - { - MessageBox.Show($"URL: {e.Parameter}"); - } - - - //_deepSeekClient = new DeepSeekClient("sk-3a3126167f1343228b1a5745bcd0bf01"); - ///// - ///// DeepSeek对象 - ///// - //private DeepSeekClient _deepSeekClient; - - ///// - ///// 系统角色设定 - ///// - //private const string SysContent = "你是 DeepSeek AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言"; - - - ///// - ///// 单轮流式聊天 - ///// - ///// - ///// - //private async void button1_Click(object sender, RoutedEventArgs e) - //{ - // try - // { - // richTextBox1.Document.Blocks.Clear(); - // //------ - // var chatReq = new ChatRequest - // { - // model = ChatModels.DeepseekChat, - // messages = new List { - // 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); - // } - //} - - ///// - ///// 单轮普通聊天 - ///// - ///// - ///// - //private async void button2_Click(object sender, RoutedEventArgs e) - //{ - // try - // { - // var chatReq = new ChatRequest - // { - // model = ChatModels.DeepseekChat, - // messages = new List { - // 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); - // } - //} - - ///// - ///// 多轮对话列表 - ///// - //private List HistoryList = new List { new MessagesItem { role = ChatRoles.System, content = SysContent } }; - - ///// - ///// 多轮流式对话 - ///// - ///// - ///// - //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); - // } - //} - - ///// - ///// 多轮普通聊天 - ///// - ///// - ///// - //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); - // } - //} - } -} diff --git a/WPFUI.Test/ChatFunction/ChatDialogueViewModel.cs b/WPFUI.Test/ChatFunction/ChatDialogueViewModel.cs deleted file mode 100644 index a270dc0..0000000 --- a/WPFUI.Test/ChatFunction/ChatDialogueViewModel.cs +++ /dev/null @@ -1,238 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; - -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -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; -using LangChain.Providers.OpenAI.Predefined; -using LangChain.Schema; - -using Markdig; -using Markdig.Wpf.ColorCode; - -using tryAGI.OpenAI; - -//using static LangChain.Chains.Chain; -namespace WPFUI.Test -{ - public partial class ChatDialogueViewModel : ObservableObject - { - static readonly DeepSeekConfiguration config = new DeepSeekConfiguration() - { - ApiKey = "sk-3a3126167f1343228b1a5745bcd0bf01", - Endpoint = "https://api.deepseek.com", - ChatSettings = new() { UseStreaming = true } - }; - private ScrollViewer scrollViewer; - /// - /// 当前AI的回复 - /// - [ObservableProperty] - public partial Message? CurrentRespone { get; set; } = Message.Ai(string.Empty); - /// - /// 发送给AI的消息,包括上下文记录 - /// - private Message? CurrentRequest { get; set; } = Message.Empty; - public MarkdownPipeline Pipeline { get; set; } = new MarkdownPipelineBuilder().UseAdvancedExtensions().UseColorCodeWpf().Build(); - - public ChatDialogueViewModel() - { - ChatHistory ??= new ObservableCollection(); - } - /// - /// 用户输入 - /// - [ObservableProperty] - [NotifyCanExecuteChangedFor(nameof(SendCommand))] - public partial string UserInput { get; set; } - private bool CanSend() - { - return !string.IsNullOrEmpty(UserInput); - } - [RelayCommand] - private async void PromptChat() - { - try - { - var deepseekLLM = new DeepSeekChatModel(new DeepSeekProvider(config)); - var prompt = new PromptTemplate(new PromptTemplateInput( - template: "Revit二次开发中,使用变量doc和uidoc两个变量,构造一个保证可以执行的C#代码块,添加相应注释,不需要方法签名和using命名空间,但使用时需要完整的命名空间。实现{需求}的功能", inputVariables: ["需求"])); - deepseekLLM.RequestSent += DeepseekLLM_RequestSent; - var chain = new LlmChain(new LlmChainInput(deepseekLLM, prompt)); - var result = await chain.CallAsync(new ChainValues(new Dictionary - { - { "需求", UserInput} - })).ConfigureAwait(true); - // The result is an object with a `text` property. - var respones = result.Value["text"].ToString(); - } - catch (Exception ex) - { - - } - } - /// - /// 历史聊天记录 - /// - public ObservableCollection ChatHistory { get; set; } - - [RelayCommand(CanExecute = nameof(CanSend), IncludeCancelCommand = true)] - private async Task SendAsync(object obj, CancellationToken cancellationToken) - { - try - { - if (obj is ScrollViewer scroll) - { - scrollViewer = scroll; - } - - ChatHistory.Add(Message.Human(UserInput)); - //UserInput.Content=string.Empty; - - - #region DeepSeek - var deepseekLLM = new DeepSeekChatModel(new DeepSeekProvider(config)); - 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); - #endregion - - // 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. - } - catch (Exception ex) - { - MessageBox.Show(ex.Message); - } - } - - private async static Task RunChainAsync() - { - try - { - var client = new OpenAiClient("sk-3a3126167f1343228b1a5745bcd0bf01"); - OpenAiProvider provider = new OpenAiProvider(client); - var llm = new OpenAiLatestFastChatModel(provider); - var embeddingModel = new TextEmbeddingV3SmallModel(provider); - var prompt = new PromptTemplate(new PromptTemplateInput( -template: "Revit二次开发中,使用变量doc和uidoc两个变量,构造一个保证可以执行的C#代码块,添加相应注释,不需要方法签名和using命名空间,但使用时需要完整的命名空间。实现{需求}的功能", inputVariables: ["需求"])); - var chain = new LlmChain(new LlmChainInput(llm, prompt)); - - 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(llm, chatPrompt) - { - Verbose = true - }); - - var resultB = await chainB.CallAsync(new ChainValues(new Dictionary(3) - { - {"input_language", "English"}, - {"output_language", "French"}, - {"text", "I love programming"}, - })); - Console.WriteLine(resultB.Value["text"]); - } - catch (Exception ex) - { - - } - } - - private void DeepseekLLM_RequestSent(object sender, ChatRequest e) - { - Debug.WriteLine("-------------RequestSent-------------"); - foreach (var mes in e.Messages) - { - Debug.WriteLine($"{mes}"); - - } - //Debug.WriteLine("-------------RequestSent-------------"); - //Debug.WriteLine($"发送者{sender}"); - //scrollViewer.Dispatcher.Invoke(() => - //{ - // ChatHistory.Add(CurrentRespone); - //}); - } - //接收完毕 - private void DeepseekLLM_ResponseReceived(object sender, ChatResponse e) - { - //Debug.WriteLine("-------------ResponseReceived-------------"); - Application.Current.Dispatcher.Invoke(() => - { - //Debug.WriteLine($"发送者:{sender};使用量:{e.Usage}"); - CurrentRequest += e.LastMessage; - CurrentRespone = Message.Ai(string.Empty); - //最后一条完整的消息 - //Debug.WriteLine($"{ChatHistory}"); - //ChatHistory.Add(e.LastMessage); - //Respones.Content += e.Content; - }); - } - //partial void OnCurrentResponeChanged(Message? value) - //{ - //} - //接收Delta - private void DeepseekLLM_DeltaReceived(object sender, ChatResponseDelta e) - { - if (string.IsNullOrEmpty(e.Content)) - { - return; - } - scrollViewer.Dispatcher.Invoke(() => - { - ChatHistory.Remove(CurrentRespone); - //Debug.WriteLine("-------------DeltaReceived-------------"); - - Debug.WriteLine($"{e.Content}"); - - CurrentRespone += Message.Ai(e.Content); - ChatHistory.Add(CurrentRespone); - Task.Delay(1); - //ChatHistory. - //判断滚动条是否在底部 - if (scrollViewer.VerticalOffset == scrollViewer.ExtentHeight - scrollViewer.ViewportHeight) - { - scrollViewer?.ScrollToEnd(); - } - //Respones.Content += e.Content; - }); - } - - [RelayCommand] - private void NewSession() - { - ChatHistory?.Clear(); - CurrentRequest = Message.Empty; - } - - } -} \ No newline at end of file diff --git a/WPFUI.Test/ChatFunction/ColorCodeBlockRenderer.cs b/WPFUI.Test/ChatFunction/ColorCodeBlockRenderer.cs deleted file mode 100644 index f6ee8b6..0000000 --- a/WPFUI.Test/ChatFunction/ColorCodeBlockRenderer.cs +++ /dev/null @@ -1,109 +0,0 @@ -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; - -namespace Markdig.Wpf.ColorCode; - -public class ColorCodeBlockRenderer : WpfObjectRenderer -{ - private readonly CodeBlockRenderer _underlyingCodeBlockRenderer; - private readonly StyleDictionary _styleDictionary; - - /// - /// Create a new with the specified and . - /// - /// The underlying CodeBlockRenderer to handle unsupported languages. - /// A StyleDictionary for custom styling. - public ColorCodeBlockRenderer(CodeBlockRenderer underlyingCodeBlockRenderer, StyleDictionary styleDictionary) - { - _underlyingCodeBlockRenderer = underlyingCodeBlockRenderer; - _styleDictionary = styleDictionary; - } - - /// - /// Writes the specified to the . - /// - /// The renderer. - /// The code block to render. - 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); - //if (string.IsNullOrEmpty(code)) - //{ - // return; - //} - 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; - //if (leafBlock.Line == 0) - //{ - // return string.Empty; - //} - - 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(); - } -} \ No newline at end of file diff --git a/WPFUI.Test/ChatFunction/ColorCodeWpfExtension.cs b/WPFUI.Test/ChatFunction/ColorCodeWpfExtension.cs deleted file mode 100644 index 25a6a5f..0000000 --- a/WPFUI.Test/ChatFunction/ColorCodeWpfExtension.cs +++ /dev/null @@ -1,55 +0,0 @@ -using ColorCode.Styling; -using Markdig.Renderers; -using Markdig.Renderers.Wpf; - -namespace Markdig.Wpf.ColorCode; - -public class ColorCodeWpfExtension : IMarkdownExtension -{ - private readonly StyleDictionary _styleDictionary; - - /// - /// Creates a new with the specified . - /// - /// A dictionary indicating how to style the code. - public ColorCodeWpfExtension(StyleDictionary styleDictionary) => _styleDictionary = styleDictionary; - - /// - /// Sets up this extension for the specified pipeline. - /// - /// The pipeline. - public void Setup(MarkdownPipelineBuilder pipeline) - { - } - - /// - /// Sets up this extension for the specified renderer. - /// - /// The pipeline used to parse the document. - /// The renderer. - public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer) - { - if (renderer is not WpfRenderer wpfRenderer) - { - return; - } - - var codeBlockRenderer = wpfRenderer.ObjectRenderers.FindExact(); - - if (codeBlockRenderer != null) - { - wpfRenderer.ObjectRenderers.Remove(codeBlockRenderer); - } - else - { - codeBlockRenderer = new CodeBlockRenderer(); - } - - wpfRenderer.ObjectRenderers.AddIfNotAlready( - new ColorCodeBlockRenderer( - codeBlockRenderer, - _styleDictionary - ) - ); - } -} diff --git a/WPFUI.Test/ChatFunction/CustomChatWindow.xaml b/WPFUI.Test/ChatFunction/CustomChatWindow.xaml deleted file mode 100644 index f84268f..0000000 --- a/WPFUI.Test/ChatFunction/CustomChatWindow.xaml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/WPFUI.Test/ChatFunction/CustomChatWindow.xaml.cs b/WPFUI.Test/ChatFunction/CustomChatWindow.xaml.cs deleted file mode 100644 index 6741e9d..0000000 --- a/WPFUI.Test/ChatFunction/CustomChatWindow.xaml.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; - -//using LangChain.Chains.LLM; -//using LangChain.DocumentLoaders; -//using LangChain.Prompts; -using LangChain.Providers; -using LangChain.Providers.DeepSeek; -using LangChain.Providers.DeepSeek.Predefined; -using LangChain.Providers.OpenAI; -using LangChain.Providers.OpenAI.Predefined; -//using LangChain.Schema; - -namespace WPFUI.Test -{ - /// - /// CustomChatWindow.xaml 的交互逻辑 - /// - public partial class CustomChatWindow : Window - { - public CustomChatWindow() - { - InitializeComponent(); - //ChatWithAI(); - //ChatWithDeepSeek(); - } - private async void ChatWithDeepSeek() - { - try - { - var Response = await DeepSeekHttpClient.Run(); - } - catch (Exception) - { - throw; - } - } - - } -} diff --git a/WPFUI.Test/ChatFunction/DeepSeekClient.cs b/WPFUI.Test/ChatFunction/DeepSeekClient.cs deleted file mode 100644 index 8d1af4b..0000000 --- a/WPFUI.Test/ChatFunction/DeepSeekClient.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; - -//using Azure; - -namespace WPFUI.Test -{ - class DeepSeekHttpClient - { - private readonly HttpClient _client; - private const string BaseUrl = "https://api.deepseek.com"; - private const string ApiUrl = "https://api.deepseek.com/chat/completions"; - private const string ApiKey = "sk-3a3126167f1343228b1a5745bcd0bf01"; // 替换为你的实际API Key - - public DeepSeekHttpClient() - { - _client = new HttpClient(); - _client.DefaultRequestHeaders.Add("Authorization", $"Bearer {ApiKey}"); - } - - public async Task GetResponseAsync(string prompt) - { - using var request = CreateRequest(prompt); - using var response = await _client.SendAsync(request); - - var responseJson = await response.Content.ReadAsStringAsync(); - if (!response.IsSuccessStatusCode) - { - throw new HttpRequestException($"API Error: {response.StatusCode}\n{responseJson}"); - } - - return ExtractResponseContent(responseJson); - } - - private HttpRequestMessage CreateRequest(string prompt) - { - var body = new - { - model = "deepseek-chat", - messages = new[] { new { role = "user", content = prompt } }, - temperature = 0.7 - }; - - return new HttpRequestMessage(HttpMethod.Post, ApiUrl) - { - Content = new StringContent( - JsonSerializer.Serialize(body), - Encoding.UTF8, - "application/json") - }; - } - - private static string ExtractResponseContent(string json) - { - using var doc = JsonDocument.Parse(json); - return doc.RootElement - .GetProperty("choices")[0] - .GetProperty("message") - .GetProperty("content") - .GetString() ?? string.Empty; - } - - public static async Task Run() - { - var client = new DeepSeekHttpClient(); - return await client.GetResponseAsync("如何学习人工智能?"); - } - } -} diff --git a/WPFUI.Test/ChatFunction/ExtensionMethods.cs b/WPFUI.Test/ChatFunction/ExtensionMethods.cs deleted file mode 100644 index b3ba493..0000000 --- a/WPFUI.Test/ChatFunction/ExtensionMethods.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -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; - } - } -} diff --git a/WPFUI.Test/ChatFunction/MarkdownPipelineBuilderExtension.cs b/WPFUI.Test/ChatFunction/MarkdownPipelineBuilderExtension.cs deleted file mode 100644 index 593e7bc..0000000 --- a/WPFUI.Test/ChatFunction/MarkdownPipelineBuilderExtension.cs +++ /dev/null @@ -1,24 +0,0 @@ -using ColorCode.Styling; - -namespace Markdig.Wpf.ColorCode; - -/// -/// Extensions for adding ColorCode to the Markdig pipeline. -/// -public static class MarkdownPipelineBuilderExtension -{ - /// - /// Use ColorCode to apply code colorization to markdown within the Markdig pipeline. - /// - /// The pipeline the ColorCode extension is being added to. - /// An optional StyleDictionary for custom styling. - /// The MarkdownPipelineBuilder with the added ColorCode extension. - public static MarkdownPipelineBuilder UseColorCodeWpf( - this MarkdownPipelineBuilder pipeline, - StyleDictionary? styleDictionary = null) - { - pipeline.Extensions.Add(new ColorCodeWpfExtension(styleDictionary ?? StyleDictionary.DefaultLight)); - - return pipeline; - } -} diff --git a/WPFUI.Test/ChatFunction/MarkdownStyleRes.xaml b/WPFUI.Test/ChatFunction/MarkdownStyleRes.xaml deleted file mode 100644 index 45d34c7..0000000 --- a/WPFUI.Test/ChatFunction/MarkdownStyleRes.xaml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/WPFUI.Test/ChatFunction/RichTextBoxFormatter.cs b/WPFUI.Test/ChatFunction/RichTextBoxFormatter.cs deleted file mode 100644 index 04abe0f..0000000 --- a/WPFUI.Test/ChatFunction/RichTextBoxFormatter.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System.Collections.Generic; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Documents; - -using ColorCode.Common; -using ColorCode.Parsing; -using ColorCode.Styling; -using ColorCode.Wpf.Common; - -namespace ColorCode.Wpf -{ - /// - /// Creates a , for rendering Syntax Highlighted code to a RichTextBlock. - /// - public class RichTextBoxFormatter : CodeColorizerBase - { - /// - /// Creates a , for rendering Syntax Highlighted code to a RichTextBlock. - /// - /// The Custom styles to Apply to the formatted Code. - /// The language parser that the instance will use for its lifetime. - public RichTextBoxFormatter(StyleDictionary? style = null, ILanguageParser? languageParser = null) : base(style, languageParser) - { - } - - /// - /// Adds Syntax Highlighted Source Code to the provided RichTextBlock. - /// - /// The source code to colorize. - /// The language to use to colorize the source code. - /// The Control to add the Text to. - public void FormatRichTextBox(string sourceCode, ILanguage language, RichTextBox richText) - { - var paragraph = new Paragraph(); - richText.Document.Blocks.Add(paragraph); - FormatInlines(sourceCode, language, paragraph.Inlines); - } - - /// - /// Adds Syntax Highlighted Source Code to the provided InlineCollection. - /// - /// The source code to colorize. - /// The language to use to colorize the source code. - /// InlineCollection to add the Text to. - 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 scopes) - { - var styleInsertions = new List(); - - 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 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 - }); - } - } -} \ No newline at end of file diff --git a/WPFUI.Test/ChatFunction/RoleToDisplayConverter.cs b/WPFUI.Test/ChatFunction/RoleToDisplayConverter.cs deleted file mode 100644 index e41b488..0000000 --- a/WPFUI.Test/ChatFunction/RoleToDisplayConverter.cs +++ /dev/null @@ -1,77 +0,0 @@ -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 WPFUI.Test -{ - 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(); - } - } -} diff --git a/WPFUI.Test/GlobalUsings.cs b/WPFUI.Test/GlobalUsings.cs deleted file mode 100644 index 46b2b6b..0000000 --- a/WPFUI.Test/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -// global using 指令 - -global using System; -global using System.Collections.Generic; -global using System.IO; diff --git a/WPFUI.Test/GlobalVariables.cs b/WPFUI.Test/GlobalVariables.cs deleted file mode 100644 index 01b0c94..0000000 --- a/WPFUI.Test/GlobalVariables.cs +++ /dev/null @@ -1,16 +0,0 @@ - -using System.Reflection; - -using WPFUI.Test.Web; - - -namespace WPFUI.Test; - -public class GlobalVariables -{ - public static string AddInPath = Assembly.GetExecutingAssembly().Location; - public static string DirAssembly = Path.GetDirectoryName(AddInPath); - - public static AuthenticationService AuthenticationService { get; } = new AuthenticationService(); - public static bool IsLogin { get; set; } = false; -} diff --git a/WPFUI.Test/MainWindow.xaml b/WPFUI.Test/MainWindow.xaml deleted file mode 100644 index fa6b41b..0000000 --- a/WPFUI.Test/MainWindow.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - -