From 36234cb529d451d33b92c014524cb8afca4ed848 Mon Sep 17 00:00:00 2001
From: GG Z <903524121@qq.com>
Date: Thu, 4 Sep 2025 22:39:00 +0800
Subject: [PATCH] =?UTF-8?q?=E5=91=BD=E5=90=8D=E7=A9=BA=E9=97=B4=E8=B0=83?=
=?UTF-8?q?=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
AddinManager/AddinManager.csproj | 76 -
AddinManager/Services/AddinManagerService.cs | 1501 -----------------
NeoUI/NeoUI/Animations/Animations.xaml | 24 +-
NeoUI/NeoUI/Assets/CommonGeometry.xaml | 28 +-
NeoUI/NeoUI/Controls/Accordion.xaml | 161 ++
NeoUI/NeoUI/Controls/Accordion.xaml.cs | 99 ++
NeoUI/NeoUI/Controls/AccordionItem.cs | 22 +
NeoUI/NeoUI/Controls/Alert.xaml | 23 +-
NeoUI/NeoUI/Controls/Anchor.xaml | 11 +-
NeoUI/NeoUI/Controls/Badge.xaml | 2 +-
NeoUI/NeoUI/Controls/ButtonsStyle.xaml | 17 +-
NeoUI/NeoUI/Controls/Card.xaml | 6 +-
NeoUI/NeoUI/Controls/Cascader.xaml | 180 +-
NeoUI/NeoUI/Controls/CheckBoxStyle.xaml | 14 +-
NeoUI/NeoUI/Controls/ChooseBox.xaml | 70 +-
NeoUI/NeoUI/Controls/ComboBoxStyle.xaml | 45 +-
NeoUI/NeoUI/Controls/DataGridStyle.xaml | 2 +-
.../Controls/Decorations/EmbossBorder.xaml | 1 +
.../Controls/Decorations/SlotBorder.xaml | 4 +-
NeoUI/NeoUI/Controls/Divider.xaml | 1 +
NeoUI/NeoUI/Controls/GroupBoxStyle.xaml | 2 +-
NeoUI/NeoUI/Controls/IconElement.xaml | 2 +-
NeoUI/NeoUI/Controls/ListBoxStyle.xaml | 22 +-
NeoUI/NeoUI/Controls/ListViewStyle.xaml | 2 +-
NeoUI/NeoUI/Controls/NeuComboBox.xaml | 101 +-
.../Notification/NotificationView.xaml | 71 +-
NeoUI/NeoUI/Controls/PaginationControl.xaml | 14 +-
NeoUI/NeoUI/Controls/PasswordBoxStyle.xaml | 143 +-
NeoUI/NeoUI/Controls/Pill.xaml | 6 +-
NeoUI/NeoUI/Controls/RadioButtonStyle.xaml | 8 +-
NeoUI/NeoUI/Controls/Spin.xaml | 10 +-
NeoUI/NeoUI/Controls/Tag.xaml | 4 +-
NeoUI/NeoUI/Controls/TextBoxStyle.xaml | 28 +-
NeoUI/NeoUI/Controls/Toast/ToastControl.xaml | 11 +-
NeoUI/NeoUI/Controls/TreeViewStyle.xaml | 17 +-
NeoUI/NeoUI/Controls/UploadArea.xaml | 4 +-
.../Internal/AlphaToPercentConverter.cs | 4 +-
.../Internal/ColorToHexConverter.cs | 4 +-
.../Internal/ColorToOpaqueColorConverter.cs | 4 +-
.../Internal/HueToBrushConverter.cs | 4 +-
.../Internal/HueToColorConverter.cs | 4 +-
NeoUI/NeoUI/NeoUI.csproj | 7 +-
NeoUI/NeoUI/Themes/Dark.xaml | 22 +-
NeoUI/NeoUI/Themes/Light.xaml | 18 +-
NeoUI/NeoUI/Themes/Styles.xaml | 1 +
NeoUI/NeoUITest/MainWindow.xaml | 203 ++-
NeoUI/NeoUITest/MainWindow.xaml.cs | 10 +-
ShrlAlgo.Addin.Test/ActionWindow.xaml | 9 +-
.../ShrlAlgo.Addin.Test.csproj | 7 +-
ShrlAlgoToolkit.Mvvm/Assists/BindingProxy.cs | 1 -
.../ShrlAlgoToolkit.Mvvm.csproj | 3 -
.../Assists/BuiltEnumDictionary.cs | 71 -
ShrlAlgoToolkit.Revit/Assists/DMUAssist.cs | 40 -
.../Assists/ParameterAssist.cs | 8 +-
.../Extensions/SpatialExtensions.cs | 6 +-
.../ShrlAlgoToolkit.Revit.projitems | 2 -
.../UIRibbon/ModifyTabApp.cs | 12 +-
ShrlAlgoToolkit.sln | 2 -
58 files changed, 933 insertions(+), 2241 deletions(-)
delete mode 100644 AddinManager/AddinManager.csproj
delete mode 100644 AddinManager/Services/AddinManagerService.cs
create mode 100644 NeoUI/NeoUI/Controls/Accordion.xaml
create mode 100644 NeoUI/NeoUI/Controls/Accordion.xaml.cs
create mode 100644 NeoUI/NeoUI/Controls/AccordionItem.cs
delete mode 100644 ShrlAlgoToolkit.Revit/Assists/BuiltEnumDictionary.cs
delete mode 100644 ShrlAlgoToolkit.Revit/Assists/DMUAssist.cs
diff --git a/AddinManager/AddinManager.csproj b/AddinManager/AddinManager.csproj
deleted file mode 100644
index 82d0340..0000000
--- a/AddinManager/AddinManager.csproj
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
- net48
- true
- x64
- x64
- 7.3
- Revit Addin Manager
- Revit插件管理器,提供插件的安装、卸载、启用/禁用、热重载等功能
- ShrlAlgo
- RevitAddinManager
- Copyright © 2024
- 1.0.0.0
- 1.0.0.0
- true
- false
- false
- REVIT_API_AVAILABLE
-
-
-
-
-
- ..\libs\2020\RevitAPI.dll
- False
-
-
- ..\libs\2020\RevitAPIUI.dll
- False
-
-
-
-
-
-
- C:\Program Files\Autodesk\Revit 2020\RevitAPI.dll
- False
-
-
- C:\Program Files\Autodesk\Revit 2020\RevitAPIUI.dll
- False
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PreserveNewest
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/AddinManager/Services/AddinManagerService.cs b/AddinManager/Services/AddinManagerService.cs
deleted file mode 100644
index 46ff63a..0000000
--- a/AddinManager/Services/AddinManagerService.cs
+++ /dev/null
@@ -1,1501 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Xml.Linq;
-
-using AddinManager.Models;
-
-using Newtonsoft.Json;
-
-namespace AddinManager.Services
-{
- ///
- /// 插件管理服务
- ///
- public class AddinManagerService
- {
- private readonly string _revitVersion;
- private readonly List _addinFolderPaths;
- private readonly string _configPath;
- private readonly Dictionary _loadedAssemblies = new Dictionary();
-
- public AddinManagerService(string revitVersion = null)
- {
- _revitVersion = revitVersion ?? DetectCurrentRevitVersion();
- _addinFolderPaths = GetAllAddinDirectories(_revitVersion);
-
- // 配置文件放在用户目录下
- var userAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
- "Autodesk", "Revit", "Addins", _revitVersion);
- _configPath = Path.Combine(userAddinPath, "AddinManagerConfig.json");
-
- EnsureDirectoriesExist();
- }
-
- ///
- /// 动态检测当前运行的Revit版本
- ///
- private string DetectCurrentRevitVersion()
- {
- try
- {
- // 方法1:从当前运行的Revit进程检测
- var revitProcesses = Process.GetProcessesByName("Revit");
- if (revitProcesses.Length > 0)
- {
- var process = revitProcesses[0];
- var version = ExtractVersionFromProcess(process);
- if (!string.IsNullOrEmpty(version))
- {
- return version;
- }
- }
-
- // 方法2:从Revit API获取版本(如果在Revit环境中运行)
- try
- {
- var app = AddinManagerApp.UiApplication.Application;
- return app.VersionNumber;
- }
- catch
- {
- // 忽略Revit API获取失败
- }
- // 方法3:从注册表获取最新安装的版本
- var installedVersions = GetInstalledRevitVersions();
- if (installedVersions.Count > 0)
- {
- return installedVersions.OrderByDescending(v => v).First();
- }
- }
- catch
- {
- // 忽略检测失败
- }
-
- // 默认返回2024版本
- return "2024";
- }
-
- ///
- /// 从进程信息中提取Revit版本
- ///
- private string ExtractVersionFromProcess(Process process)
- {
- try
- {
- var fileName = process.MainModule?.FileName;
- if (!string.IsNullOrEmpty(fileName))
- {
- var directory = Path.GetDirectoryName(fileName);
- if (directory != null)
- {
- // 从路径中提取版本号
- for (int year = 2018; year <= 2030; year++)
- {
- if (directory.Contains(year.ToString()))
- {
- return year.ToString();
- }
- }
- }
-
- // 从文件版本信息中获取
- var versionInfo = FileVersionInfo.GetVersionInfo(fileName);
- if (versionInfo.ProductVersion != null)
- {
- var match = System.Text.RegularExpressions.Regex.Match(versionInfo.ProductVersion, @"(\d{4})");
- if (match.Success)
- {
- return match.Groups[1].Value;
- }
- }
- }
- }
- catch
- {
- // 忽略错误
- }
- return null;
- }
-
- ///
- /// 获取系统中安装的所有Revit版本
- ///
- private List GetInstalledRevitVersions()
- {
- var versions = new HashSet();
-
- try
- {
- // 从注册表获取
- using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Autodesk\Revit"))
- {
- if (key != null)
- {
- foreach (var subKeyName in key.GetSubKeyNames())
- {
- if (int.TryParse(subKeyName, out int year) && year >= 2018 && year <= 2030)
- {
- versions.Add(subKeyName);
- }
- }
- }
- }
-
- // 从WOW6432Node获取
- using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Autodesk\Revit"))
- {
- if (key != null)
- {
- foreach (var subKeyName in key.GetSubKeyNames())
- {
- if (int.TryParse(subKeyName, out int year) && year >= 2018 && year <= 2030)
- {
- versions.Add(subKeyName);
- }
- }
- }
- }
-
- // 从文件系统检查
- var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
- var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
-
- foreach (var baseDir in new[] { programFiles, programFilesX86 })
- {
- if (string.IsNullOrEmpty(baseDir)) continue;
-
- var autodeskDir = Path.Combine(baseDir, "Autodesk");
- if (Directory.Exists(autodeskDir))
- {
- foreach (var dir in Directory.GetDirectories(autodeskDir, "Revit *"))
- {
- var dirName = Path.GetFileName(dir);
- var match = System.Text.RegularExpressions.Regex.Match(dirName, @"Revit (\d{4})");
- if (match.Success)
- {
- versions.Add(match.Groups[1].Value);
- }
- }
- }
- }
- }
- catch
- {
- // 忽略错误
- }
-
- return versions.ToList();
- }
-
- ///
- /// 获取所有可能的插件目录
- ///
- private List GetAllAddinDirectories(string revitVersion)
- {
- var directories = new List();
-
- // 1. 用户级插件目录 (当前用户) - .addin文件
- var userAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
- "Autodesk", "Revit", "Addins", revitVersion);
- directories.Add(userAddinPath);
-
- // 2. 用户级ApplicationPlugins目录 - .bundle文件夹
- var userAppPluginsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
- "Autodesk", "ApplicationPlugins");
- directories.Add(userAppPluginsPath);
-
- // 3. 全局插件目录 (所有用户) - .addin文件
- var globalAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
- "Autodesk", "Revit", "Addins", revitVersion);
- directories.Add(globalAddinPath);
-
- // 4. 全局ApplicationPlugins目录 - .bundle文件夹
- var globalAppPluginsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
- "Autodesk", "ApplicationPlugins");
- directories.Add(globalAppPluginsPath);
-
- // 5. 程序文件目录下的通用插件目录
- var programFilesAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
- "Autodesk", $"Revit {revitVersion}", "AddIns");
- if (Directory.Exists(programFilesAddinPath))
- {
- directories.Add(programFilesAddinPath);
- }
-
- // 6. 程序文件(x86)目录下的插件目录
- var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
- if (!string.IsNullOrEmpty(programFilesX86))
- {
- var programFilesX86AddinPath = Path.Combine(programFilesX86, "Autodesk", $"Revit {revitVersion}", "AddIns");
- if (Directory.Exists(programFilesX86AddinPath))
- {
- directories.Add(programFilesX86AddinPath);
- }
- }
-
- // 去重并返回存在的目录
- return directories.Distinct().Where(Directory.Exists).ToList();
- }
-
- ///
- /// 获取Revit的安装路径
- ///
- private List GetRevitInstallPaths(string revitVersion)
- {
- var installPaths = new List();
-
- try
- {
- // 从注册表查找Revit安装路径
- using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey($@"SOFTWARE\Autodesk\Revit\{revitVersion}"))
- {
- if (key != null)
- {
- var installPath = key.GetValue("InstallationPath") as string;
- if (!string.IsNullOrEmpty(installPath) && Directory.Exists(installPath))
- {
- installPaths.Add(installPath);
- }
- }
- }
-
- // 从注册表查找其他可能的路径 (WOW6432Node for 32-bit apps on 64-bit Windows)
- using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey($@"SOFTWARE\WOW6432Node\Autodesk\Revit\{revitVersion}"))
- {
- if (key != null)
- {
- var installPath = key.GetValue("InstallationPath") as string;
- if (!string.IsNullOrEmpty(installPath) && Directory.Exists(installPath))
- {
- installPaths.Add(installPath);
- }
- }
- }
- }
- catch
- {
- // 忽略注册表读取错误
- }
-
- // 如果注册表查找失败,尝试常见的安装路径
- var commonPaths = new[]
- {
- Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Autodesk", $"Revit {revitVersion}"),
- Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Autodesk", $"Revit {revitVersion}"),
- Path.Combine("C:", "Program Files", "Autodesk", $"Revit {revitVersion}"),
- Path.Combine("C:", "Program Files (x86)", "Autodesk", $"Revit {revitVersion}")
- };
-
- foreach (var path in commonPaths)
- {
- if (Directory.Exists(path))
- {
- installPaths.Add(path);
- }
- }
-
- return installPaths.Distinct().ToList();
- }
-
- ///
- /// 获取所有已安装的插件(包括已禁用的和Bundle格式的)
- ///
- public List GetInstalledAddins()
- {
- var addins = new List();
-
- // 扫描所有插件目录
- foreach (var addinFolderPath in _addinFolderPaths)
- {
- if (!Directory.Exists(addinFolderPath))
- continue;
-
- try
- {
- // 检查是否是ApplicationPlugins目录(Bundle格式)
- if (addinFolderPath.Contains("ApplicationPlugins"))
- {
- // 扫描Bundle格式插件
- var bundleAddins = ScanBundlePlugins(addinFolderPath);
- addins.AddRange(bundleAddins);
- }
- else
- {
- // 扫描传统.addin文件格式
- var traditionalAddins = ScanTraditionalAddins(addinFolderPath);
- addins.AddRange(traditionalAddins);
- }
- }
- catch (Exception ex)
- {
- // 记录目录访问错误
- var errorAddin = new AddinInfo
- {
- Name = $"目录访问错误: {Path.GetFileName(addinFolderPath)}",
- AddinFilePath = addinFolderPath,
- SourceDirectory = addinFolderPath,
- HasErrors = true,
- ErrorMessages = new List { $"无法访问目录: {ex.Message}" },
- Status = "访问错误",
- IsEnabled = false
- };
- addins.Add(errorAddin);
- }
- }
-
- return addins;
- }
-
- ///
- /// 扫描传统.addin文件格式的插件
- ///
- private List ScanTraditionalAddins(string addinFolderPath)
- {
- var addins = new List();
-
- // 扫描所有.addin文件(包括.disabled文件)
- var addinFiles = Directory.GetFiles(addinFolderPath, "*.addin", SearchOption.AllDirectories)
- .Concat(Directory.GetFiles(addinFolderPath, "*.addin.disabled", SearchOption.AllDirectories))
- .ToArray();
-
- foreach (var addinFile in addinFiles)
- {
- try
- {
- var addinInfos = ParseAddinFile(addinFile);
- foreach (var addinInfo in addinInfos)
- {
- // 标记插件来源目录
- addinInfo.SourceDirectory = addinFolderPath;
- addins.Add(addinInfo);
- }
- }
- catch (Exception ex)
- {
- // 记录解析错误
- var errorAddin = new AddinInfo
- {
- Name = Path.GetFileNameWithoutExtension(addinFile),
- AddinFilePath = addinFile,
- SourceDirectory = addinFolderPath,
- HasErrors = true,
- ErrorMessages = new List { ex.Message },
- Status = "解析错误",
- IsEnabled = false
- };
- addins.Add(errorAddin);
- }
- }
-
- return addins;
- }
-
- ///
- /// 扫描Bundle格式的插件(.bundle文件夹)
- ///
- private List ScanBundlePlugins(string appPluginsPath)
- {
- var addins = new List();
-
- // 查找所有.bundle文件夹
- var bundleFolders = Directory.GetDirectories(appPluginsPath, "*.bundle", SearchOption.TopDirectoryOnly);
-
- foreach (var bundleFolder in bundleFolders)
- {
- try
- {
- // 查找PackageContents.xml文件
- var packageContentsPath = Path.Combine(bundleFolder, "PackageContents.xml");
- if (File.Exists(packageContentsPath))
- {
- var bundleAddins = ParseBundlePackage(packageContentsPath, bundleFolder);
- addins.AddRange(bundleAddins);
- }
- else
- {
- // 如果没有PackageContents.xml,记录为错误
- var errorAddin = new AddinInfo
- {
- Name = Path.GetFileNameWithoutExtension(bundleFolder),
- AddinFilePath = bundleFolder,
- SourceDirectory = appPluginsPath,
- HasErrors = true,
- ErrorMessages = new List { "Bundle文件夹中缺少PackageContents.xml文件" },
- Status = "Bundle格式错误",
- IsEnabled = false
- };
- addins.Add(errorAddin);
- }
- }
- catch (Exception ex)
- {
- // 记录Bundle解析错误
- var errorAddin = new AddinInfo
- {
- Name = Path.GetFileNameWithoutExtension(bundleFolder),
- AddinFilePath = bundleFolder,
- SourceDirectory = appPluginsPath,
- HasErrors = true,
- ErrorMessages = new List { $"Bundle解析错误: {ex.Message}" },
- Status = "Bundle解析错误",
- IsEnabled = false
- };
- addins.Add(errorAddin);
- }
- }
-
- return addins;
- }
-
- ///
- /// 解析Bundle格式的PackageContents.xml文件
- ///
- private List ParseBundlePackage(string packageContentsPath, string bundleFolder)
- {
- var addins = new List();
- var doc = XDocument.Load(packageContentsPath);
-
- // 获取Bundle的基本信息
- var packageElement = doc.Element("ApplicationPackage");
- if (packageElement == null) return addins;
-
- var bundleName = packageElement.Attribute("Name")?.Value ?? Path.GetFileNameWithoutExtension(bundleFolder);
- var bundleVersion = packageElement.Attribute("Version")?.Value ?? "Unknown";
- var bundleDescription = packageElement.Attribute("Description")?.Value ?? "";
- var bundleAuthor = packageElement.Attribute("Author")?.Value ?? "Unknown";
-
- // 查找支持的Revit版本
- var supportedVersions = new List();
- var componentsElement = packageElement.Element("Components");
- if (componentsElement != null)
- {
- foreach (var runtimeRequirements in componentsElement.Descendants("RuntimeRequirements"))
- {
- var platform = runtimeRequirements.Attribute("Platform")?.Value;
- var version = runtimeRequirements.Attribute("Version")?.Value;
-
- if (platform == "Revit" && !string.IsNullOrEmpty(version))
- {
- supportedVersions.Add(version);
- }
- }
- }
-
- // 查找所有的AddIn元素
- foreach (var componentElement in componentsElement?.Elements("ComponentEntry") ?? Enumerable.Empty())
- {
- var moduleType = componentElement.Attribute("ModuleType")?.Value;
- if (moduleType != "Managed") continue; // 只处理托管代码插件
-
- var appName = componentElement.Attribute("AppName")?.Value ?? bundleName;
- var appDescription = componentElement.Attribute("AppDescription")?.Value ?? bundleDescription;
-
- // 检查是否被禁用(通过重命名bundle文件夹)
- bool isDisabled = bundleFolder.EndsWith(".bundle.disabled") || bundleFolder.EndsWith(".disabled");
-
- var addin = new AddinInfo
- {
- Name = appName,
- Description = appDescription,
- Version = bundleVersion,
- Developer = bundleAuthor,
- AddinFilePath = packageContentsPath,
- SourceDirectory = Path.GetDirectoryName(bundleFolder),
- Type = AddinType.Application, // Bundle通常是Application类型
- CurrentRevitVersion = _revitVersion,
- LastModified = File.GetLastWriteTime(packageContentsPath),
- IsEnabled = !isDisabled,
- Status = isDisabled ? "已禁用" : "已启用"
- };
-
- // 添加支持的版本
- foreach (var version in supportedVersions)
- {
- addin.SupportedRevitVersions.Add(version);
- }
-
- // 查找程序集路径
- var appModule = componentElement.Element("AppModule");
- if (appModule != null)
- {
- var relativePath = appModule.Value;
- if (!string.IsNullOrEmpty(relativePath))
- {
- var assemblyPath = Path.Combine(bundleFolder, "Contents", relativePath);
- addin.AssemblyPath = assemblyPath;
-
- // 尝试获取程序集版本信息
- if (File.Exists(assemblyPath))
- {
- try
- {
- var assembly = Assembly.LoadFrom(assemblyPath);
- var assemblyVersion = assembly.GetName().Version?.ToString();
- if (!string.IsNullOrEmpty(assemblyVersion))
- {
- addin.Version = assemblyVersion;
- }
-
- // 查找主类
- var types = assembly.GetTypes();
- var appType = types.FirstOrDefault(t => t.GetInterfaces()
- .Any(i => i.Name.Contains("IExternalApplication")));
- if (appType != null)
- {
- addin.ClassName = appType.FullName;
- }
- }
- catch
- {
- // 忽略程序集加载错误
- }
- }
- }
- }
-
- addins.Add(addin);
- }
-
- return addins;
- }
-
- ///
- /// 启用插件 - 支持传统.addin文件和Bundle格式
- ///
- public bool EnableAddin(AddinInfo addin)
- {
- try
- {
- // 检查是否是Bundle格式插件
- if (IsBundlePlugin(addin))
- {
- return EnableBundlePlugin(addin);
- }
- else
- {
- return EnableTraditionalPlugin(addin);
- }
- }
- catch (Exception ex)
- {
- addin.ErrorMessages.Add($"启用失败: {ex.Message}");
- return false;
- }
- }
-
- ///
- /// 禁用插件 - 支持传统.addin文件和Bundle格式
- ///
- public bool DisableAddin(AddinInfo addin)
- {
- try
- {
- // 检查是否是Bundle格式插件
- if (IsBundlePlugin(addin))
- {
- return DisableBundlePlugin(addin);
- }
- else
- {
- return DisableTraditionalPlugin(addin);
- }
- }
- catch (Exception ex)
- {
- addin.ErrorMessages.Add($"禁用失败: {ex.Message}");
- return false;
- }
- }
-
- ///
- /// 检查是否是Bundle格式插件
- ///
- private bool IsBundlePlugin(AddinInfo addin)
- {
- return addin.AddinFilePath.Contains("ApplicationPlugins") &&
- addin.AddinFilePath.EndsWith("PackageContents.xml");
- }
-
- ///
- /// 启用传统.addin文件格式插件
- ///
- private bool EnableTraditionalPlugin(AddinInfo addin)
- {
- if (!File.Exists(addin.AddinFilePath))
- return false;
-
- // 如果文件以.disabled结尾,重命名回.addin
- if (addin.AddinFilePath.EndsWith(".disabled"))
- {
- string enabledPath = addin.AddinFilePath.Replace(".addin.disabled", ".addin");
- File.Move(addin.AddinFilePath, enabledPath);
- addin.AddinFilePath = enabledPath;
- }
-
- addin.IsEnabled = true;
- SaveAddinState(addin);
- return true;
- }
-
- ///
- /// 禁用传统.addin文件格式插件
- ///
- private bool DisableTraditionalPlugin(AddinInfo addin)
- {
- if (!File.Exists(addin.AddinFilePath))
- return false;
-
- // 如果文件以.addin结尾,重命名为.addin.disabled
- if (addin.AddinFilePath.EndsWith(".addin"))
- {
- string disabledPath = addin.AddinFilePath + ".disabled";
- File.Move(addin.AddinFilePath, disabledPath);
- addin.AddinFilePath = disabledPath;
- }
-
- addin.IsEnabled = false;
- SaveAddinState(addin);
- return true;
- }
-
- ///
- /// 启用Bundle格式插件
- ///
- private bool EnableBundlePlugin(AddinInfo addin)
- {
- var bundleFolder = Path.GetDirectoryName(addin.AddinFilePath);
- if (!Directory.Exists(bundleFolder))
- return false;
-
- // 如果Bundle文件夹以.disabled结尾,重命名回.bundle
- if (bundleFolder.EndsWith(".disabled"))
- {
- string enabledPath = bundleFolder.Replace(".bundle.disabled", ".bundle");
- Directory.Move(bundleFolder, enabledPath);
-
- // 更新插件信息中的路径
- addin.AddinFilePath = Path.Combine(enabledPath, "PackageContents.xml");
- addin.SourceDirectory = Path.GetDirectoryName(enabledPath);
- }
- else if (bundleFolder.EndsWith(".bundle.disabled"))
- {
- string enabledPath = bundleFolder.Replace(".bundle.disabled", ".bundle");
- Directory.Move(bundleFolder, enabledPath);
-
- // 更新插件信息中的路径
- addin.AddinFilePath = Path.Combine(enabledPath, "PackageContents.xml");
- addin.SourceDirectory = Path.GetDirectoryName(enabledPath);
- }
-
- addin.IsEnabled = true;
- SaveAddinState(addin);
- return true;
- }
-
- ///
- /// 禁用Bundle格式插件
- ///
- private bool DisableBundlePlugin(AddinInfo addin)
- {
- var bundleFolder = Path.GetDirectoryName(addin.AddinFilePath);
- if (!Directory.Exists(bundleFolder))
- return false;
-
- // 如果Bundle文件夹以.bundle结尾,重命名为.bundle.disabled
- if (bundleFolder.EndsWith(".bundle"))
- {
- string disabledPath = bundleFolder + ".disabled";
- Directory.Move(bundleFolder, disabledPath);
-
- // 更新插件信息中的路径
- addin.AddinFilePath = Path.Combine(disabledPath, "PackageContents.xml");
- addin.SourceDirectory = Path.GetDirectoryName(disabledPath);
- }
-
- addin.IsEnabled = false;
- SaveAddinState(addin);
- return true;
- }
-
- ///
- /// 卸载插件
- ///
- public bool UninstallAddin(AddinInfo addin)
- {
- try
- {
- // 删除.addin文件
- if (File.Exists(addin.AddinFilePath))
- {
- File.Delete(addin.AddinFilePath);
- }
-
- // 删除程序集文件(如果在插件目录下)
- if (File.Exists(addin.AssemblyPath) &&
- _addinFolderPaths.Any(path => addin.AssemblyPath.StartsWith(path)))
- {
- File.Delete(addin.AssemblyPath);
- }
-
- RemoveAddinState(addin);
- return true;
- }
- catch (Exception ex)
- {
- addin.ErrorMessages.Add($"卸载失败: {ex.Message}");
- return false;
- }
- }
-
- ///
- /// 热重载插件 - 增强版本
- ///
- public bool HotReloadAddin(AddinInfo addin)
- {
- try
- {
- // 先禁用插件
- if (addin.IsEnabled)
- {
- DisableAddin(addin);
- }
-
- // 卸载已加载的程序集
- if (_loadedAssemblies.ContainsKey(addin.AssemblyPath))
- {
- _loadedAssemblies.Remove(addin.AssemblyPath);
- }
-
- // 等待一段时间确保���件释放
- System.Threading.Thread.Sleep(500);
-
- // 重新启用插件
- EnableAddin(addin);
-
- addin.LastModified = File.GetLastWriteTime(addin.AssemblyPath);
- return true;
- }
- catch (Exception ex)
- {
- addin.ErrorMessages.Add($"热重载失败: {ex.Message}");
- return false;
- }
- }
-
- ///
- /// 安装插件
- ///
- public bool InstallAddin(string addinFilePath, string targetDirectory = null)
- {
- try
- {
- if (targetDirectory == null)
- {
- // 默认安装到用户插件目录(第一个目录)
- targetDirectory = _addinFolderPaths.FirstOrDefault() ??
- Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
- "Autodesk", "Revit", "Addins", _revitVersion);
- }
-
- var fileName = Path.GetFileName(addinFilePath);
- var targetPath = Path.Combine(targetDirectory, fileName);
-
- File.Copy(addinFilePath, targetPath, true);
- return true;
- }
- catch (Exception)
- {
- return false;
- }
- }
-
- ///
- /// 检查插件兼容性
- ///
- public bool CheckCompatibility(AddinInfo addin)
- {
- return addin.SupportedRevitVersions.Contains(_revitVersion) ||
- addin.SupportedRevitVersions.Count == 0;
- }
-
- ///
- /// 获取插件错误日志
- ///
- public List GetAddinErrors(AddinInfo addin)
- {
- return addin.ErrorMessages;
- }
-
- ///
- /// 安装临时调试插件 - 直接加载到Revit中
- ///
- public bool InstallTemporaryDebugAddin(CommandInfo commandInfo, string commandName)
- {
- try
- {
-#if REVIT_API_AVAILABLE
- // 直接通过Revit API加载插件
- var uiApp = AddinManagerApp.UiApplication;
- if (uiApp == null)
- {
- System.Diagnostics.Debug.WriteLine("Revit应用程序未初始化");
- return false;
- }
-
- // 加载程序集
- var assembly = Assembly.LoadFrom(commandInfo.AssemblyPath);
- var commandType = assembly.GetType(commandInfo.ClassName);
-
- if (commandType == null)
- {
- System.Diagnostics.Debug.WriteLine($"无法找到类型: {commandInfo.ClassName}");
- return false;
- }
-
- // 创建外部命令数据
- var commandData = new Autodesk.Revit.UI.ExternalCommandData();
-
- // 将命令添加到临时调试命令列表
- var tempCommandId = $"DebugCmd_{DateTime.Now:yyyyMMdd_HHmmss}_{Guid.NewGuid().ToString("N")[..8]}";
-
- // 创建临时按钮(可选,用于UI访问)
- try
- {
- var ribbonTab = uiApp.GetRibbonTabs().FirstOrDefault(t => t == "调试") ??
- uiApp.CreateRibbonTab("调试");
-
- var panel = uiApp.GetRibbonPanels("调试").FirstOrDefault(p => p.Name == "临时命令") ??
- uiApp.CreateRibbonPanel("调试", "临时命令");
-
- var buttonData = new Autodesk.Revit.UI.PushButtonData(
- tempCommandId,
- commandName,
- commandInfo.AssemblyPath,
- commandInfo.ClassName);
-
- var button = panel.AddItem(buttonData) as Autodesk.Revit.UI.PushButton;
- if (button != null)
- {
- button.ToolTip = $"临时调试命令: {commandName}";
- button.LongDescription = $"从 {Path.GetFileName(commandInfo.AssemblyPath)} 加载的调试命令";
- }
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"创建临时按钮失败: {ex.Message}");
- // 即使按钮创建失败,命令仍然可以通过其他方式调用
- }
-
- // 记录已加载的临时命令
- if (!_loadedAssemblies.ContainsKey(commandInfo.AssemblyPath))
- {
- _loadedAssemblies.Add(commandInfo.AssemblyPath, assembly);
- }
-
- return true;
-#else
- // 在没有Revit API的环境中,仍然创建.addin文件作为fallback
- return CreateTemporaryAddinFile(commandInfo, commandName);
-#endif
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"直接加载插件失败: {ex.Message}");
- return false;
- }
- }
-
- ///
- /// 创建临时.addin文件作为备用方案
- ///
- private bool CreateTemporaryAddinFile(CommandInfo commandInfo, string commandName)
- {
- try
- {
- // 确保用户插件目录存在
- var userAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
- "Autodesk", "Revit", "Addins", _revitVersion);
-
- if (!Directory.Exists(userAddinPath))
- {
- Directory.CreateDirectory(userAddinPath);
- }
-
- // 生成临时插件的唯一标识
- var tempAddinId = $"DebugAddin_{DateTime.Now:yyyyMMdd_HHmmss}_{Guid.NewGuid().ToString("N")[..8]}";
- var tempAddinFileName = $"{tempAddinId}.addin";
- var tempAddinFilePath = Path.Combine(userAddinPath, tempAddinFileName);
-
- // 创建临时.addin文件内容
- var addinXml = CreateDebugAddinXml(commandInfo, commandName, tempAddinId);
-
- // 写入.addin文件
- File.WriteAllText(tempAddinFilePath, addinXml);
-
- return true;
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"创建临时addin文件失败: {ex.Message}");
- return false;
- }
- }
-
- ///
- /// 直接执行命令(用于调试测试)
- ///
- public bool ExecuteCommand(CommandInfo commandInfo)
- {
- try
- {
-#if REVIT_API_AVAILABLE
- var uiApp = AddinManagerApp.UiApplication;
- if (uiApp == null) return false;
-
- // 加载程序集
- var assembly = Assembly.LoadFrom(commandInfo.AssemblyPath);
- var commandType = assembly.GetType(commandInfo.ClassName);
-
- if (commandType == null) return false;
-
- // 创建命令实例
- var commandInstance = Activator.CreateInstance(commandType) as Autodesk.Revit.UI.IExternalCommand;
- if (commandInstance == null) return false;
-
- // 准备命令数据
- var commandData = new Autodesk.Revit.UI.ExternalCommandData
- {
- Application = uiApp,
- JournalData = new Autodesk.Revit.DB.NameValueMap()
- };
-
- var message = string.Empty;
- var elementSet = new Autodesk.Revit.DB.ElementSet();
-
- // 执行命令
- var result = commandInstance.Execute(commandData, ref message, elementSet);
-
- return result == Autodesk.Revit.UI.Result.Succeeded;
-#else
- return false;
-#endif
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"执行命令失败: {ex.Message}");
- return false;
- }
- }
-
- ///
- /// 卸载临时调试插件
- ///
- public bool UnloadTemporaryDebugAddin(string assemblyPath)
- {
- try
- {
- // 从已加载程序集列表中移除
- if (_loadedAssemblies.ContainsKey(assemblyPath))
- {
- _loadedAssemblies.Remove(assemblyPath);
- }
-
- // 释放程序集引用
- ReleaseDllReferences();
-
- return true;
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"卸载临时插件失败: {ex.Message}");
- return false;
- }
- }
-
- ///
- /// 创建调试插件的XML内容
- ///
- private string CreateDebugAddinXml(CommandInfo commandInfo, string commandName, string addinId)
- {
- var xml = $@"
-
-
- {commandName}
- {commandInfo.AssemblyPath}
- {commandInfo.ClassName}
- 临时调试插件 - {commandName}
- AddinManager.Debug
- Revit插件管理器调试功能
- {_revitVersion}
- {commandInfo.TransactionMode}
-
-";
-
- return xml;
- }
-
- ///
- /// 从DLL中获取命令信息
- ///
- public List GetCommandsFromDll(string dllPath)
- {
- var commands = new List();
-
- try
- {
- if (!File.Exists(dllPath))
- {
- return commands;
- }
-
- // 加载程序集
- var assembly = Assembly.LoadFrom(dllPath);
-
- // 查找实现IExternalCommand接口的类
- foreach (var type in assembly.GetTypes())
- {
- if (type.IsClass && !type.IsAbstract)
- {
- // 检查是否实现了IExternalCommand接口
- var interfaces = type.GetInterfaces();
- bool implementsIExternalCommand = false;
-
- foreach (var interfaceType in interfaces)
- {
- if (interfaceType.Name == "IExternalCommand" ||
- interfaceType.FullName?.Contains("IExternalCommand") == true)
- {
- implementsIExternalCommand = true;
- break;
- }
- }
-
- if (implementsIExternalCommand)
- {
- var commandInfo = new CommandInfo
- {
- ClassName = type.FullName,
- AssemblyPath = dllPath,
- Assembly = assembly,
- Type = type,
- TransactionMode = GetTransactionMode(type)
- };
-
- commands.Add(commandInfo);
- }
- }
- }
- }
- catch (Exception ex)
- {
- // 返回错误信息
- var errorCommand = new CommandInfo
- {
- ClassName = "Error",
- AssemblyPath = dllPath,
- HasErrors = true,
- ErrorMessage = ex.Message
- };
- commands.Add(errorCommand);
- }
-
- return commands;
- }
-
- ///
- /// 获取命令的事务模式
- ///
- private string GetTransactionMode(Type type)
- {
- try
- {
- // 查找Transaction特性
- var transactionAttribute = type.GetCustomAttributes(false)
- .FirstOrDefault(attr => attr.GetType().Name.Contains("Transaction"));
-
- if (transactionAttribute != null)
- {
- // 尝试获取事务模式值
- var modeProperty = transactionAttribute.GetType().GetProperty("Mode");
- if (modeProperty != null)
- {
- var modeValue = modeProperty.GetValue(transactionAttribute);
- return modeValue?.ToString() ?? "Manual";
- }
- }
-
- return "Manual"; // 默认事务模式
- }
- catch
- {
- return "Manual";
- }
- }
-
- ///
- /// 附加到Revit进程进行调试
- ///
- public bool AttachToRevitProcess()
- {
- try
- {
- var revitProcesses = Process.GetProcessesByName("Revit");
- if (revitProcesses.Length == 0)
- {
- return false;
- }
-
- // 如果有多个Revit进程,选择第一个
- var revitProcess = revitProcesses[0];
- var processId = revitProcess.Id;
-
- // 尝试启动Visual Studio并附加到进程
- var vsInstances = GetVisualStudioInstances();
- if (vsInstances.Count > 0)
- {
- var vsPath = vsInstances.First();
- var startInfo = new ProcessStartInfo
- {
- FileName = vsPath,
- Arguments = $"/debugexe",
- UseShellExecute = true
- };
-
- Process.Start(startInfo);
- return true;
- }
-
- return false;
- }
- catch
- {
- return false;
- }
- }
-
- ///
- /// 获取已安装的Visual Studio实例
- ///
- private List GetVisualStudioInstances()
- {
- var instances = new List();
-
- try
- {
- // 查找Visual Studio的常见安装路径
- var possiblePaths = new[]
- {
- @"Microsoft Visual Studio\2022\Enterprise\Common7\IDE\devenv.exe",
- @"Microsoft Visual Studio\2022\Professional\Common7\IDE\devenv.exe",
- @"Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.exe",
- @"Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe",
- @"Microsoft Visual Studio\2019\Professional\Common7\IDE\devenv.exe",
- @"Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.exe"
- };
-
- var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
- var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
-
- foreach (var basePath in new[] { programFiles, programFilesX86 })
- {
- if (string.IsNullOrEmpty(basePath)) continue;
-
- foreach (var relativePath in possiblePaths)
- {
- var fullPath = Path.Combine(basePath, relativePath);
- if (File.Exists(fullPath))
- {
- instances.Add(fullPath);
- }
- }
- }
- }
- catch
- {
- // 忽略错误
- }
-
- return instances;
- }
-
- ///
- /// 清理临时调试插件
- ///
- public void CleanupTemporaryDebugAddins()
- {
- try
- {
- var userAddinPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
- "Autodesk", "Revit", "Addins", _revitVersion);
-
- if (!Directory.Exists(userAddinPath)) return;
-
- // 查找所有临时调试插件文件
- var tempFiles = Directory.GetFiles(userAddinPath, "DebugAddin_*.addin");
-
- foreach (var tempFile in tempFiles)
- {
- try
- {
- // 检查文件是否超过1天,如果是则删除
- var fileInfo = new FileInfo(tempFile);
- if (DateTime.Now - fileInfo.CreationTime > TimeSpan.FromDays(1))
- {
- File.Delete(tempFile);
- }
- }
- catch
- {
- // 忽略单个文件删除失败
- }
- }
- }
- catch
- {
- // 忽略清理错误
- }
- }
-
- ///
- /// 释放程序集引用以便重新编译
- ///
- public void ReleaseDllReferences()
- {
- try
- {
- _loadedAssemblies.Clear();
-
- // 强制垃圾回收
- GC.Collect();
- GC.WaitForPendingFinalizers();
- GC.Collect();
- }
- catch
- {
- // 忽略错误
- }
- }
-
- private void EnsureDirectoriesExist()
- {
- foreach (var directory in _addinFolderPaths)
- {
- if (!Directory.Exists(directory))
- {
- try
- {
- Directory.CreateDirectory(directory);
- }
- catch
- {
- // 忽略创建目录失败
- }
- }
- }
- }
-
- private void SaveAddinState(AddinInfo addin)
- {
- try
- {
- var states = new Dictionary();
-
- if (File.Exists(_configPath))
- {
- var json = File.ReadAllText(_configPath);
- states = JsonConvert.DeserializeObject>(json) ?? new Dictionary();
- }
-
- var key = $"{addin.ClassName}|{Path.GetFileNameWithoutExtension(addin.AddinFilePath)}";
- states[key] = addin.IsEnabled;
-
- var updatedJson = JsonConvert.SerializeObject(states, Formatting.Indented);
- File.WriteAllText(_configPath, updatedJson);
- }
- catch
- {
- // 忽略保存错误
- }
- }
-
- private void RemoveAddinState(AddinInfo addin)
- {
- try
- {
- if (!File.Exists(_configPath))
- return;
-
- var json = File.ReadAllText(_configPath);
- var states = JsonConvert.DeserializeObject>(json);
-
- if (states != null)
- {
- var key = $"{addin.ClassName}|{Path.GetFileNameWithoutExtension(addin.AddinFilePath)}";
- if (states.ContainsKey(key))
- {
- states.Remove(key);
- var updatedJson = JsonConvert.SerializeObject(states, Formatting.Indented);
- File.WriteAllText(_configPath, updatedJson);
- }
- }
- }
- catch
- {
- // 忽略错误
- }
- }
-
- ///
- /// 解析.addin文件
- ///
- private List ParseAddinFile(string addinFilePath)
- {
- var addins = new List();
- var doc = XDocument.Load(addinFilePath);
-
- // 判断文件是否被禁用(通过文件扩展名)
- bool isDisabled = addinFilePath.EndsWith(".disabled");
-
- foreach (var addinElement in doc.Descendants("AddIn"))
- {
- var addin = new AddinInfo
- {
- AddinFilePath = addinFilePath,
- CurrentRevitVersion = _revitVersion,
- LastModified = File.GetLastWriteTime(addinFilePath),
- IsEnabled = !isDisabled
- };
-
- // 解析类型
- var typeAttr = addinElement.Attribute("Type")?.Value;
- switch (typeAttr)
- {
- case "Command":
- addin.Type = AddinType.Command;
- break;
- case "Application":
- addin.Type = AddinType.Application;
- break;
- case "ExternalDBApplication":
- addin.Type = AddinType.ExternalDBApplication;
- break;
- default:
- addin.Type = AddinType.Unknown;
- break;
- }
-
- addin.Name = addinElement.Element("Name")?.Value ?? "Unknown";
- addin.Description = addinElement.Element("Description")?.Value ?? "";
- addin.AssemblyPath = addinElement.Element("Assembly")?.Value ?? "";
- addin.ClassName = addinElement.Element("FullClassName")?.Value ?? "";
- addin.Developer = addinElement.Element("VendorId")?.Value ?? "Unknown";
-
- // 解析版本兼容性
- var versionElements = addinElement.Elements("SupportedVersion");
- foreach (var versionElement in versionElements)
- {
- addin.SupportedRevitVersions.Add(versionElement.Value);
- }
-
- // 如果程序集路径是相对路径,转换为绝对路径
- if (!Path.IsPathRooted(addin.AssemblyPath))
- {
- addin.AssemblyPath = Path.Combine(Path.GetDirectoryName(addinFilePath), addin.AssemblyPath);
- }
-
- // 尝试获取程序集版本信息
- if (File.Exists(addin.AssemblyPath))
- {
- try
- {
- var assembly = Assembly.LoadFrom(addin.AssemblyPath);
- addin.Version = assembly.GetName().Version?.ToString() ?? "Unknown";
- }
- catch
- {
- addin.Version = "Unknown";
- }
- }
-
- addins.Add(addin);
- }
-
- return addins;
- }
-
- ///
- /// 获取正在运行的Revit进程
- ///
- public List GetRevitProcesses()
- {
- var processes = new List();
-
- try
- {
- var revitProcesses = Process.GetProcessesByName("Revit");
-
- foreach (var process in revitProcesses)
- {
- try
- {
- var processInfo = new ProcessInfo
- {
- Id = process.Id,
- ProcessName = process.ProcessName,
- WindowTitle = process.MainWindowTitle,
- StartTime = process.StartTime
- };
- processes.Add(processInfo);
- }
- catch
- {
- // 忽略无法访问的进程
- }
- }
- }
- catch
- {
- // 忽略获取进程失败
- }
-
- return processes;
- }
-
- ///
- /// 清理调试插件
- ///
- public void CleanupDebugAddins()
- {
- try
- {
- // 清理临时调试文件
- CleanupTemporaryDebugAddins();
-
- // 释放程序集引用
- ReleaseDllReferences();
-
- System.Diagnostics.Debug.WriteLine("调试插件清理完成");
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"清理调试插件失败: {ex.Message}");
- }
- }
- }
-
- ///
- /// 进程信息模型
- ///
- public class ProcessInfo
- {
- public int Id { get; set; }
- public string ProcessName { get; set; }
- public string WindowTitle { get; set; }
- public DateTime StartTime { get; set; }
- }
-}
diff --git a/NeoUI/NeoUI/Animations/Animations.xaml b/NeoUI/NeoUI/Animations/Animations.xaml
index 71ee311..2079a22 100644
--- a/NeoUI/NeoUI/Animations/Animations.xaml
+++ b/NeoUI/NeoUI/Animations/Animations.xaml
@@ -118,10 +118,20 @@
Storyboard.TargetProperty="Opacity"
To="0.2" />
-
+
+
+
-
\ No newline at end of file
diff --git a/NeoUI/NeoUI/Assets/CommonGeometry.xaml b/NeoUI/NeoUI/Assets/CommonGeometry.xaml
index 35052b2..f7ab91e 100644
--- a/NeoUI/NeoUI/Assets/CommonGeometry.xaml
+++ b/NeoUI/NeoUI/Assets/CommonGeometry.xaml
@@ -12,31 +12,31 @@
+
-
M567.7 514.9l254.8-254.6c15.4-15.4 15.4-40.3 0-55.6-15.4-15.4-40.3-15.4-55.6 0L512 459.2 257.1 204.6c-15.4-15.4-40.3-15.4-55.6 0-15.4 15.4-15.4 40.3 0 55.6l254.8 254.6-254.8 254.7c-15.4 15.4-15.4 40.3 0 55.6 7.7 7.7 17.8 11.5 27.8 11.5 10.1 0 20.1-3.8 27.8-11.5L512 570.5l254.9 254.7c7.7 7.7 17.7 11.5 27.8 11.5 10.1 0 20.1-3.8 27.8-11.5 15.4-15.4 15.4-40.3 0-55.6L567.7 514.9z
M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3-22.2-52.4-53.9-99.4-94.3-139.9-40.4-40.4-87.5-72.2-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3 0.1 19.9-16 36-35.9 36z
M512 384c19.9 0 36-16.1 36-36V36c0-19.9-16.1-36-36-36s-36 16.1-36 36v312c0 19.9 16.1 36 36 36zM512 1024c-69.1 0-136.2-13.5-199.3-40.2C251.7 958 197 921 150 874c-47-47-84-101.7-109.8-162.7C13.5 648.2 0 581.1 0 512c0-81.3 18.5-159.1 55-231.2 34.8-68.7 85.7-129.7 147.2-176.5 15.8-12 38.4-9 50.4 6.8s9 38.4-6.8 50.4c-52.8 40.2-96.6 92.7-126.5 151.7C87.9 375.3 72 442.1 72 512c0 59.4 11.6 117 34.6 171.3 22.2 52.4 53.9 99.5 94.3 139.9 40.4 40.4 87.5 72.2 139.9 94.3C395 940.4 452.6 952 512 952c59.4 0 117-11.6 171.3-34.6 52.4-22.2 99.5-53.9 139.9-94.3 40.4-40.4 72.2-87.5 94.3-139.9C940.4 629 952 571.4 952 512c0-69.9-15.9-136.7-47.3-198.6-29.9-59.1-73.7-111.5-126.5-151.7-15.8-12-18.9-34.6-6.8-50.4 12-15.8 34.6-18.9 50.4-6.8C883.2 151.3 934.1 212.3 969 281c36.5 72.1 55 149.8 55 231.2 0 69.1-13.5 136.2-40.2 199.3C958 772.3 921 827 874 874s-101.8 83.9-162.7 109.7c-63.1 26.8-130.2 40.3-199.3 40.3z
M949.5 898.5L743.8 692.9C798.9 626.4 832 541.1 832 448c0-212.1-171.9-384-384-384S64 235.9 64 448s171.9 384 384 384c93.1 0 178.4-33.1 244.9-88.2l205.7 205.7c7 7 16.2 10.5 25.5 10.5s18.4-3.5 25.5-10.5c13.9-14.1 13.9-36.9-0.1-51z m-380.1-163C531 751.8 490.2 760 448 760s-83-8.2-121.4-24.5c-37.1-15.7-70.5-38.2-99.2-66.9-28.7-28.7-51.2-62.1-66.9-99.2C144.2 531 136 490.2 136 448s8.2-83 24.5-121.4c15.7-37.1 38.2-70.5 66.9-99.2 28.7-28.7 62.1-51.2 99.2-66.9C365 144.2 405.8 136 448 136s83 8.2 121.4 24.5c37.1 15.7 70.5 38.2 99.2 66.9 28.7 28.7 51.2 62.1 66.9 99.2C751.8 365 760 405.8 760 448s-8.2 83-24.5 121.4c-15.7 37.1-38.2 70.5-66.9 99.2-28.7 28.7-62 51.2-99.2 66.9z
M858.5 763.6c-18.9-44.8-46.1-85-80.6-119.5-34.5-34.5-74.7-61.6-119.5-80.6-0.4-0.2-0.8-0.3-1.2-0.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-0.4 0.2-0.8 0.3-1.2 0.5-44.8 18.9-85 46-119.5 80.6-34.5 34.5-61.6 74.7-80.6 119.5C146.9 807.5 137 854 136 901.8c-0.1 4.5 3.5 8.2 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c0.1 4.4 3.6 7.8 8 7.8h60c4.5 0 8.1-3.7 8-8.2-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z
- M721.3 305.6L393.8 634.1l-85.4-149.5c-9.9-17.3-31.8-23.3-49.1-13.4S236 503 245.9 520.3l108.8 190.5c6.6 11.6 18.8 18.2 31.3 18.2 6.1 0 12.2-1.5 17.8-4.7 3.2-1.9 6.1-4.1 8.5-6.7l0.4-0.4 359.5-360.6c14-14.1 14-36.9-0.1-50.9-14-14.2-36.7-14.2-50.8-0.1zM512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m311.1 823.1c-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952c-59.4 0-117-11.6-171.2-34.5-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512c0-59.4 11.6-117 34.5-171.2 22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512c0 59.4-11.6 117-34.5 171.2-22.2 52.4-53.9 99.5-94.4 139.9z
- M512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m311.1 823.1c-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952c-59.4 0-117-11.6-171.2-34.5-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512c0-59.4 11.6-117 34.5-171.2 22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512c0 59.4-11.6 117-34.5 171.2-22.2 52.4-53.9 99.5-94.4 139.9zM630.2 705.6H545V355.5c0-19.9-16.1-36-36-36h-96c-19.9 0-36 16.1-36 36s16.1 36 36 36h60v314.1h-85.2c-19.9 0-36 16.1-36 36s16.1 36 36 36H630.2c19.9 0 36-16.1 36-36s-16.1-36-36-36zM473 220.5a36 36 0 1 0 72 0 36 36 0 1 0-72 0z
- M512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512s-11.6 117-34.5 171.2c-22.2 52.4-53.9 99.4-94.3 139.9-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952s-117-11.6-171.2-34.5c-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512s11.6-117 34.5-171.2c22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72m0-72C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m0 640c-22.1 0-40-17.9-40-40V231c0-22.1 17.9-40 40-40s40 17.9 40 40v369c0 22.1-17.9 40-40 40z m-45 109a45 45 0 1 0 90 0 45 45 0 1 0-90 0z
- M717.2 306.2c-14.1-14-36.9-14-50.9 0.1L512 461 357.7 306.3c-14-14.1-36.8-14.1-50.9-0.1-14.1 14-14.1 36.8-0.1 50.9L461.2 512 306.7 666.9c-14 14.1-14 36.9 0.1 50.9 7 7 16.2 10.5 25.4 10.5s18.5-3.5 25.5-10.6L512 563l154.3 154.8c7 7.1 16.3 10.6 25.5 10.6s18.4-3.5 25.4-10.5c14.1-14 14.1-36.8 0.1-50.9L562.8 512l154.4-154.9c14.1-14.1 14.1-36.9 0-50.9zM512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m311.1 823.1c-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952c-59.4 0-117-11.6-171.2-34.5-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512c0-59.4 11.6-117 34.5-171.2 22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512c0 59.4-11.6 117-34.5 171.2-22.2 52.4-53.9 99.5-94.4 139.9z
- M963.4 511.7c-0.3-5.6-8.9-33.3-20.9-62.1-12.3-29.7-33.1-72.7-61.9-108.6-37.7-47.2-84.2-84.9-138.2-111.9-66.3-33.3-143.9-50.1-230.5-50.1-86.5 0-164.1 16.9-230.4 50.2C227.9 256 181.4 293.6 143.3 341c-28.8 36-49.5 79-61.8 108.7-12 28.8-20.5 56.5-20.8 62.1v0.4c0.3 5.6 8.9 33.3 20.9 62.2 12.4 29.7 33.1 72.7 61.8 108.5 37.7 47.2 84.2 84.9 138.2 111.9 66.7 33.4 144.2 50.3 230.4 50.3 86.3 0 163.8-16.9 230.4-50.3 53.8-26.9 100.3-64.6 138.2-111.8 28.8-35.9 49.6-78.9 61.9-108.6 12-28.8 20.6-56.5 20.9-62.1v-0.2-0.4z m-74.2 0.2c-5.7 17.4-27.8 80.2-64.4 125.8l-0.5 0.5c-31.1 39-69.6 70.1-114.3 92.6-56.5 28.3-123.3 42.7-198.4 42.7-75.2 0-141.9-14.4-198.4-42.7-44.6-22.3-83-53.5-114.3-92.7-36.8-45.8-59-108.8-64.7-126.3 5.7-17.4 27.9-80.3 64.7-126.3 31.4-39.2 69.9-70.3 114.4-92.6 56.6-28.3 123.4-42.6 198.6-42.6 75.5 0 142.2 14.3 198.3 42.6 44.6 22.3 83 53.5 114.3 92.7 36.8 46 59 108.9 64.7 126.3zM511.9 337.8c-95.6 0-173.3 77.8-173.3 173.3s77.8 173.3 173.3 173.3 173.3-77.8 173.3-173.3-77.7-173.3-173.3-173.3z m102 173.3c0 27.2-10.6 52.8-29.9 72.1-19.3 19.3-44.9 29.9-72.1 29.9-27.2 0-52.8-10.6-72.1-29.9-19.3-19.3-29.9-44.9-29.9-72.1 0-27.2 10.6-52.8 29.9-72.1 19.3-19.3 44.9-29.9 72.1-29.9 27.2 0 52.8 10.6 72.1 29.9 19.3 19.3 29.9 44.9 29.9 72.1z
M895.7 300.1c0 9.6-3.2 19.3-9.6 27.4L545.2 751.3c-8.3 10.3-20.8 16.3-34.1 16.3-13.2 0-25.8-6-34-16.3L138 329.3c-15.1-18.8-12.1-46.3 6.7-61.4 18.8-15.1 46.3-12.1 61.4 6.7l305.1 379.6L818 272.7c15.1-18.8 42.6-21.8 61.4-6.7 10.7 8.7 16.3 21.3 16.3 34.1z
M895.7 659.9c0-9.6-3.2-19.3-9.6-27.4L545.2 208.7c-8.3-10.3-20.8-16.3-34.1-16.3-13.2 0-25.8 6-34 16.3L138 630.7c-15.1 18.8-12.1 46.3 6.7 61.4 18.8 15.1 46.3 12.1 61.4-6.7l305.1-379.6L818 687.3c15.1 18.8 42.6 21.8 61.4 6.7 10.7-8.7 16.3-21.3 16.3-34.1z
M832 464h-68V240c0-70.7-57.3-128-128-128H388c-70.7 0-128 57.3-128 128v224h-68c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V496c0-17.7-14.3-32-32-32zM332 240c0-30.9 25.1-56 56-56h248c30.9 0 56 25.1 56 56v224H332V240z m460 600H232V536h560v304zM484 701v53c0 4.4 3.6 8 8 8h40c4.4 0 8-3.6 8-8v-53c12.1-8.7 20-22.9 20-39 0-26.5-21.5-48-48-48s-48 21.5-48 48c0 16.1 7.9 30.3 20 39z
+
+
+ M721.3 305.6L393.8 634.1l-85.4-149.5c-9.9-17.3-31.8-23.3-49.1-13.4S236 503 245.9 520.3l108.8 190.5c6.6 11.6 18.8 18.2 31.3 18.2 6.1 0 12.2-1.5 17.8-4.7 3.2-1.9 6.1-4.1 8.5-6.7l0.4-0.4 359.5-360.6c14-14.1 14-36.9-0.1-50.9-14-14.2-36.7-14.2-50.8-0.1zM512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m311.1 823.1c-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952c-59.4 0-117-11.6-171.2-34.5-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512c0-59.4 11.6-117 34.5-171.2 22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512c0 59.4-11.6 117-34.5 171.2-22.2 52.4-53.9 99.5-94.4 139.9z
+
+ M512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m311.1 823.1c-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952c-59.4 0-117-11.6-171.2-34.5-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512c0-59.4 11.6-117 34.5-171.2 22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512c0 59.4-11.6 117-34.5 171.2-22.2 52.4-53.9 99.5-94.4 139.9zM630.2 705.6H545V355.5c0-19.9-16.1-36-36-36h-96c-19.9 0-36 16.1-36 36s16.1 36 36 36h60v314.1h-85.2c-19.9 0-36 16.1-36 36s16.1 36 36 36H630.2c19.9 0 36-16.1 36-36s-16.1-36-36-36zM473 220.5a36 36 0 1 0 72 0 36 36 0 1 0-72 0z
+
+ M512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512s-11.6 117-34.5 171.2c-22.2 52.4-53.9 99.4-94.3 139.9-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952s-117-11.6-171.2-34.5c-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512s11.6-117 34.5-171.2c22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72m0-72C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m0 640c-22.1 0-40-17.9-40-40V231c0-22.1 17.9-40 40-40s40 17.9 40 40v369c0 22.1-17.9 40-40 40z m-45 109a45 45 0 1 0 90 0 45 45 0 1 0-90 0z
+
+ M717.2 306.2c-14.1-14-36.9-14-50.9 0.1L512 461 357.7 306.3c-14-14.1-36.8-14.1-50.9-0.1-14.1 14-14.1 36.8-0.1 50.9L461.2 512 306.7 666.9c-14 14.1-14 36.9 0.1 50.9 7 7 16.2 10.5 25.4 10.5s18.5-3.5 25.5-10.6L512 563l154.3 154.8c7 7.1 16.3 10.6 25.5 10.6s18.4-3.5 25.4-10.5c14.1-14 14.1-36.8 0.1-50.9L562.8 512l154.4-154.9c14.1-14.1 14.1-36.9 0-50.9zM512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m311.1 823.1c-40.4 40.4-87.5 72.2-139.9 94.3C629 940.4 571.4 952 512 952c-59.4 0-117-11.6-171.2-34.5-52.4-22.2-99.4-53.9-139.9-94.3-40.4-40.4-72.2-87.5-94.3-139.9C83.6 629 72 571.4 72 512c0-59.4 11.6-117 34.5-171.2 22.2-52.4 53.9-99.4 94.3-139.9 40.4-40.4 87.5-72.2 139.9-94.3C395 83.6 452.6 72 512 72c59.4 0 117 11.6 171.2 34.5 52.4 22.2 99.4 53.9 139.9 94.3 40.4 40.4 72.2 87.5 94.3 139.9C940.4 395 952 452.6 952 512c0 59.4-11.6 117-34.5 171.2-22.2 52.4-53.9 99.5-94.4 139.9z
-
-
+
\ No newline at end of file
diff --git a/NeoUI/NeoUI/Controls/Accordion.xaml b/NeoUI/NeoUI/Controls/Accordion.xaml
new file mode 100644
index 0000000..e3d11e4
--- /dev/null
+++ b/NeoUI/NeoUI/Controls/Accordion.xaml
@@ -0,0 +1,161 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NeoUI/NeoUI/Controls/Accordion.xaml.cs b/NeoUI/NeoUI/Controls/Accordion.xaml.cs
new file mode 100644
index 0000000..1e34d7c
--- /dev/null
+++ b/NeoUI/NeoUI/Controls/Accordion.xaml.cs
@@ -0,0 +1,99 @@
+using System.Windows;
+using System.Windows.Controls;
+
+namespace NeoUI.Controls
+{
+ public class Accordion : ItemsControl
+ {
+ static Accordion()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(Accordion), new FrameworkPropertyMetadata(typeof(Accordion)));
+ }
+
+ protected override bool IsItemItsOwnContainerOverride(object item)
+ {
+ return item is AccordionItem;
+ }
+
+ protected override DependencyObject GetContainerForItemOverride()
+ {
+ return new AccordionItem();
+ }
+
+ protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ {
+ base.OnItemsChanged(e);
+
+ if (e.NewItems != null)
+ {
+ // 注意:这里需要确保 e.NewItems 中的项是 AccordionItem 类型
+ // 当通过 ItemsSource 绑定时,它们最初是数据项,在 GetContainerForItemOverride 之后才被包装
+ // 因此,事件处理最好在容器生成后进行。
+ // 为了简单起见,我们在此处添加事件,但这依赖于 ItemsSource 中的项已经是 AccordionItem。
+ // 一个更健壮的方法是重写 PrepareContainerForItemOverride。
+ foreach (AccordionItem item in e.NewItems)
+ {
+ item.PreviewMouseLeftButtonDown += AccordionItem_PreviewMouseLeftButtonDown;
+ }
+ }
+ if (e.OldItems != null)
+ {
+ foreach (AccordionItem item in e.OldItems)
+ {
+ item.PreviewMouseLeftButtonDown -= AccordionItem_PreviewMouseLeftButtonDown;
+ }
+ }
+ }
+
+ // 重写此方法是处理数据绑定时添加事件的更可靠方式
+ protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
+ {
+ base.PrepareContainerForItemOverride(element, item);
+ if (element is AccordionItem accordionItem)
+ {
+ accordionItem.PreviewMouseLeftButtonDown -= AccordionItem_PreviewMouseLeftButtonDown; // 防止重复添加
+ accordionItem.PreviewMouseLeftButtonDown += AccordionItem_PreviewMouseLeftButtonDown;
+ }
+ }
+
+ protected override void ClearContainerForItemOverride(DependencyObject element, object item)
+ {
+ if (element is AccordionItem accordionItem)
+ {
+ accordionItem.PreviewMouseLeftButtonDown -= AccordionItem_PreviewMouseLeftButtonDown;
+ }
+ base.ClearContainerForItemOverride(element, item);
+ }
+
+ private void AccordionItem_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ if (sender is AccordionItem clickedItem)
+ {
+ // 如果点击一个已展开的项的头部,则折叠它
+ if (clickedItem.IsExpanded)
+ {
+ // 检查点击的原始源是否是 ToggleButton 或其子元素
+ if (e.OriginalSource is FrameworkElement fe && fe.TemplatedParent is System.Windows.Controls.Primitives.ToggleButton)
+ {
+ clickedItem.IsExpanded = false;
+ e.Handled = true; // 阻止事件继续传播
+ }
+ }
+ else // 否则展开点击的项,并折叠其他所有项
+ {
+ // 遍历 ItemsControl 中的所有容器
+ for (int i = 0; i < Items.Count; i++)
+ {
+ var container = ItemContainerGenerator.ContainerFromIndex(i) as AccordionItem;
+ if (container != null && container != clickedItem)
+ {
+ container.IsExpanded = false;
+ }
+ }
+ clickedItem.IsExpanded = true;
+ e.Handled = true;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NeoUI/NeoUI/Controls/AccordionItem.cs b/NeoUI/NeoUI/Controls/AccordionItem.cs
new file mode 100644
index 0000000..a5976d1
--- /dev/null
+++ b/NeoUI/NeoUI/Controls/AccordionItem.cs
@@ -0,0 +1,22 @@
+using System.Windows;
+using System.Windows.Controls;
+
+namespace NeoUI.Controls
+{
+ public class AccordionItem : HeaderedContentControl
+ {
+ static AccordionItem()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(AccordionItem), new FrameworkPropertyMetadata(typeof(AccordionItem)));
+ }
+
+ public static readonly DependencyProperty IsExpandedProperty =
+ DependencyProperty.Register("IsExpanded", typeof(bool), typeof(AccordionItem), new PropertyMetadata(false));
+
+ public bool IsExpanded
+ {
+ get { return (bool)GetValue(IsExpandedProperty); }
+ set { SetValue(IsExpandedProperty, value); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NeoUI/NeoUI/Controls/Alert.xaml b/NeoUI/NeoUI/Controls/Alert.xaml
index 1f954e2..dbd3fae 100644
--- a/NeoUI/NeoUI/Controls/Alert.xaml
+++ b/NeoUI/NeoUI/Controls/Alert.xaml
@@ -1,16 +1,17 @@
+ xmlns:converters="clr-namespace:NeoUI.Converters"
+ xmlns:decorations="clr-namespace:NeoUI.Controls.Decorations">
-
+
-->
-
+
+
+
+
+
+
+
+
@@ -214,19 +238,19 @@
-
+
-
+
-
-
+
+
-
-
+
+
@@ -234,15 +258,15 @@
-
-
+
+
-
-
-
+
+
+
@@ -293,6 +317,7 @@
+
diff --git a/NeoUI/NeoUI/Controls/Pill.xaml b/NeoUI/NeoUI/Controls/Pill.xaml
index f5d722b..bc64534 100644
--- a/NeoUI/NeoUI/Controls/Pill.xaml
+++ b/NeoUI/NeoUI/Controls/Pill.xaml
@@ -1,7 +1,7 @@
@@ -20,7 +20,7 @@
-
-
+
diff --git a/NeoUI/NeoUI/Controls/RadioButtonStyle.xaml b/NeoUI/NeoUI/Controls/RadioButtonStyle.xaml
index 5040f09..f3fb206 100644
--- a/NeoUI/NeoUI/Controls/RadioButtonStyle.xaml
+++ b/NeoUI/NeoUI/Controls/RadioButtonStyle.xaml
@@ -1,6 +1,6 @@
@@ -46,7 +46,10 @@
-
+
@@ -122,7 +125,7 @@
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Visibility="Collapsed"
x:Name="Placeholder" />
-
+
+
+
+
+
+
+
+
+
+
+
@@ -292,7 +308,7 @@
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Visibility="Collapsed"
x:Name="Placeholder" />
-
+
-
+
+
+
+
-
+
-
+
-
+
-
+
diff --git a/NeoUI/NeoUI/Controls/TreeViewStyle.xaml b/NeoUI/NeoUI/Controls/TreeViewStyle.xaml
index 9a6d351..692c3d2 100644
--- a/NeoUI/NeoUI/Controls/TreeViewStyle.xaml
+++ b/NeoUI/NeoUI/Controls/TreeViewStyle.xaml
@@ -152,18 +152,23 @@
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/NeoUI/NeoUI/Controls/UploadArea.xaml b/NeoUI/NeoUI/Controls/UploadArea.xaml
index 14975fa..a407214 100644
--- a/NeoUI/NeoUI/Controls/UploadArea.xaml
+++ b/NeoUI/NeoUI/Controls/UploadArea.xaml
@@ -1,6 +1,6 @@
@@ -135,7 +135,7 @@
-
+
diff --git a/NeoUI/NeoUI/Converters/Internal/AlphaToPercentConverter.cs b/NeoUI/NeoUI/Converters/Internal/AlphaToPercentConverter.cs
index aeb49eb..1113c26 100644
--- a/NeoUI/NeoUI/Converters/Internal/AlphaToPercentConverter.cs
+++ b/NeoUI/NeoUI/Converters/Internal/AlphaToPercentConverter.cs
@@ -13,7 +13,7 @@ internal class AlphaToPercentConverter : IValueConverter
{
public static readonly AlphaToPercentConverter Instance = new();
///
- public object Convert(object? value, System.Type targetType, object? parameter, CultureInfo culture)
+ public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is byte alpha)
{
@@ -25,7 +25,7 @@ internal class AlphaToPercentConverter : IValueConverter
}
///
- public object ConvertBack(object? value, System.Type targetType, object? parameter, CultureInfo culture)
+ public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is string percentStr)
{
diff --git a/NeoUI/NeoUI/Converters/Internal/ColorToHexConverter.cs b/NeoUI/NeoUI/Converters/Internal/ColorToHexConverter.cs
index efe1132..97c5801 100644
--- a/NeoUI/NeoUI/Converters/Internal/ColorToHexConverter.cs
+++ b/NeoUI/NeoUI/Converters/Internal/ColorToHexConverter.cs
@@ -11,10 +11,10 @@ namespace NeoUI.Converters.Internal;
internal class ColorToHexConverter : IValueConverter
{
public static readonly ColorToHexConverter Instance = new();
- public object Convert(object? value, System.Type t, object? p, CultureInfo c) =>
+ public object Convert(object? value, Type t, object? p, CultureInfo c) =>
value is Color color ? $"#{color.A:X2}{color.R:X2}{color.G:X2}{color.B:X2}".ToUpper() : "#FFFFFFFF";
- public object? ConvertBack(object? value, System.Type t, object? p, CultureInfo c)
+ public object? ConvertBack(object? value, Type t, object? p, CultureInfo c)
{
if (value is not string hexStr || string.IsNullOrWhiteSpace(hexStr))
{
diff --git a/NeoUI/NeoUI/Converters/Internal/ColorToOpaqueColorConverter.cs b/NeoUI/NeoUI/Converters/Internal/ColorToOpaqueColorConverter.cs
index ab54209..439d58c 100644
--- a/NeoUI/NeoUI/Converters/Internal/ColorToOpaqueColorConverter.cs
+++ b/NeoUI/NeoUI/Converters/Internal/ColorToOpaqueColorConverter.cs
@@ -13,7 +13,7 @@ internal class ColorToOpaqueColorConverter : IValueConverter
public static readonly ColorToOpaqueColorConverter Instance = new();
///
public object Convert(object? value,
- System.Type t,
+ Type t,
object? p,
CultureInfo cul) =>
value is Color c
@@ -24,7 +24,7 @@ internal class ColorToOpaqueColorConverter : IValueConverter
///
public object ConvertBack(object? v,
- System.Type t,
+ Type t,
object? p,
CultureInfo c) =>
Binding.DoNothing;
diff --git a/NeoUI/NeoUI/Converters/Internal/HueToBrushConverter.cs b/NeoUI/NeoUI/Converters/Internal/HueToBrushConverter.cs
index 91f6b3c..4f760c7 100644
--- a/NeoUI/NeoUI/Converters/Internal/HueToBrushConverter.cs
+++ b/NeoUI/NeoUI/Converters/Internal/HueToBrushConverter.cs
@@ -22,7 +22,7 @@ internal class HueToBrushConverter : IValueConverter
/// 文化信息,提供关于语言、国家/地区等的信息,以支持区域性特定的转换,本方法中未使用。
/// 如果输入值是有效的int类型色相值,则返回对应的颜色画刷;否则返回一个透明画刷。
public object Convert(object? value,
- System.Type t,
+ Type t,
object? p,
CultureInfo c) =>
value is int hue
@@ -42,7 +42,7 @@ internal class HueToBrushConverter : IValueConverter
/// 由于方法未实现,实际上不返回任何有意义的数据,并且总是抛出异常。
/// 始终抛出此异常,因为ConvertBack方法在当前版本中没有具体实现。
public object ConvertBack(object? v,
- System.Type t,
+ Type t,
object? p,
CultureInfo c) =>
Binding.DoNothing;
diff --git a/NeoUI/NeoUI/Converters/Internal/HueToColorConverter.cs b/NeoUI/NeoUI/Converters/Internal/HueToColorConverter.cs
index cbffbf3..118c60b 100644
--- a/NeoUI/NeoUI/Converters/Internal/HueToColorConverter.cs
+++ b/NeoUI/NeoUI/Converters/Internal/HueToColorConverter.cs
@@ -15,7 +15,7 @@ namespace NeoUI.Converters.Internal;
internal class HueToColorConverter : IValueConverter
{
public object Convert(object? value,
- System.Type t,
+ Type t,
object? p,
CultureInfo c) =>
value is int hue
@@ -25,7 +25,7 @@ internal class HueToColorConverter : IValueConverter
255)
: Colors.Transparent;
- public object ConvertBack(object? value, System.Type t, object? p, CultureInfo c)
+ public object ConvertBack(object? value, Type t, object? p, CultureInfo c)
{
if (value is Color color)
{
diff --git a/NeoUI/NeoUI/NeoUI.csproj b/NeoUI/NeoUI/NeoUI.csproj
index 64310d2..1231c9a 100644
--- a/NeoUI/NeoUI/NeoUI.csproj
+++ b/NeoUI/NeoUI/NeoUI.csproj
@@ -37,16 +37,11 @@
-
-
-
-
-
-
diff --git a/NeoUI/NeoUI/Themes/Dark.xaml b/NeoUI/NeoUI/Themes/Dark.xaml
index f32ac94..6d7ff7d 100644
--- a/NeoUI/NeoUI/Themes/Dark.xaml
+++ b/NeoUI/NeoUI/Themes/Dark.xaml
@@ -119,7 +119,7 @@
#1B5E20
-
+
+
+
+
+
#e0e6ed
- #657075
+ #6d7a7d
#767676
#1C1E22
- #757575
+ #595b60
-
+
+
\ No newline at end of file
diff --git a/NeoUI/NeoUI/Themes/Light.xaml b/NeoUI/NeoUI/Themes/Light.xaml
index b4f2c1f..96861a8 100644
--- a/NeoUI/NeoUI/Themes/Light.xaml
+++ b/NeoUI/NeoUI/Themes/Light.xaml
@@ -119,7 +119,7 @@
#186A3B
-
+
- #FFFFFF
+ #EFF2F7
#50000000
-
-
+
+
+
-
+
\ No newline at end of file
diff --git a/NeoUI/NeoUI/Themes/Styles.xaml b/NeoUI/NeoUI/Themes/Styles.xaml
index a5b3d7e..b7144e8 100644
--- a/NeoUI/NeoUI/Themes/Styles.xaml
+++ b/NeoUI/NeoUI/Themes/Styles.xaml
@@ -54,6 +54,7 @@
+
diff --git a/NeoUI/NeoUITest/MainWindow.xaml b/NeoUI/NeoUITest/MainWindow.xaml
index e8f9c55..aa83862 100644
--- a/NeoUI/NeoUITest/MainWindow.xaml
+++ b/NeoUI/NeoUITest/MainWindow.xaml
@@ -156,45 +156,38 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
+
@@ -287,15 +280,11 @@
-
-
-
+
-
-
@@ -996,7 +985,7 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
new Area(i, GetJapaneseRegionName(i)))
.ToArray();
- public IEnumerable Items { get; set; }
+ public ObservableCollection Items { get; set; }
- public struct RadioItem
+ public class RadioItem
{
- public string Label;
- public string Value;
+ public string Label { get; set; }
+ public string Value { get; set; }
}
#endregion
@@ -156,7 +156,7 @@ public partial class MainWindow
InitializeStaffData();
// 初始化单选项
- Items = new[]
+ Items = new ObservableCollection()
{
new RadioItem { Label = "Apple", Value = "Apple" },
new RadioItem { Label = "Pear", Value = "Pear" },
diff --git a/ShrlAlgo.Addin.Test/ActionWindow.xaml b/ShrlAlgo.Addin.Test/ActionWindow.xaml
index 7095d1c..3ccbfec 100644
--- a/ShrlAlgo.Addin.Test/ActionWindow.xaml
+++ b/ShrlAlgo.Addin.Test/ActionWindow.xaml
@@ -22,14 +22,11 @@
-->
-
-
+
diff --git a/ShrlAlgo.Addin.Test/ShrlAlgo.Addin.Test.csproj b/ShrlAlgo.Addin.Test/ShrlAlgo.Addin.Test.csproj
index a01d3c9..1ea58ea 100644
--- a/ShrlAlgo.Addin.Test/ShrlAlgo.Addin.Test.csproj
+++ b/ShrlAlgo.Addin.Test/ShrlAlgo.Addin.Test.csproj
@@ -31,10 +31,9 @@
-
-
-
-
+
+
+
diff --git a/ShrlAlgoToolkit.Mvvm/Assists/BindingProxy.cs b/ShrlAlgoToolkit.Mvvm/Assists/BindingProxy.cs
index 02f60f3..e414ab1 100644
--- a/ShrlAlgoToolkit.Mvvm/Assists/BindingProxy.cs
+++ b/ShrlAlgoToolkit.Mvvm/Assists/BindingProxy.cs
@@ -15,7 +15,6 @@ namespace ShrlAlgoToolkit.Mvvm.Assists
set { SetValue(DataProperty, value); }
}
- // Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty = DependencyProperty.Register(
nameof(Data),
typeof(object),
diff --git a/ShrlAlgoToolkit.Mvvm/ShrlAlgoToolkit.Mvvm.csproj b/ShrlAlgoToolkit.Mvvm/ShrlAlgoToolkit.Mvvm.csproj
index f64e4db..e162be4 100644
--- a/ShrlAlgoToolkit.Mvvm/ShrlAlgoToolkit.Mvvm.csproj
+++ b/ShrlAlgoToolkit.Mvvm/ShrlAlgoToolkit.Mvvm.csproj
@@ -18,7 +18,4 @@
-
-
-
\ No newline at end of file
diff --git a/ShrlAlgoToolkit.Revit/Assists/BuiltEnumDictionary.cs b/ShrlAlgoToolkit.Revit/Assists/BuiltEnumDictionary.cs
deleted file mode 100644
index 46b4de1..0000000
--- a/ShrlAlgoToolkit.Revit/Assists/BuiltEnumDictionary.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using Autodesk.Revit.DB;
-
-namespace ShrlAlgoToolkit.Revit.Assists
-{
- public static class BuiltEnumDictionary
- {
-#if REVIT2025
- public static string ToLabel(this ForgeTypeId source)
- {
- if (ParameterUtils.IsBuiltInParameter(source)) return LabelUtils.GetLabelForBuiltInParameter(source);
- if (ParameterUtils.IsBuiltInGroup(source)) return LabelUtils.GetLabelForGroup(source);
- if (UnitUtils.IsUnit(source)) return LabelUtils.GetLabelForUnit(source);
- if (UnitUtils.IsSymbol(source)) return LabelUtils.GetLabelForSymbol(source);
- if (SpecUtils.IsSpec(source)) return LabelUtils.GetLabelForSpec(source);
- return LabelUtils.GetLabelForDiscipline(source);
- }
-#endif
-
- public static Dictionary GetBuiltInDictionary()
- where T : Enum
- {
- var dict = new Dictionary();
- foreach (object enumItem in Enum.GetValues(typeof(T)))
- {
- string name = string.Empty;
- switch (enumItem)
- {
-#if REVIT2020
- case BuiltInCategory category:
- name = LabelUtils.GetLabelFor(category);
- break;
-#endif
- case BuiltInParameter param:
- name = LabelUtils.GetLabelFor(param);
- break;
-#if REVIT2018 || REVIT2020
- case ParameterType type:
- name = LabelUtils.GetLabelFor(type);
- break;
- case BuiltInParameterGroup group:
- name = LabelUtils.GetLabelFor(group);
- break;
- case UnitType unitType:
- name = LabelUtils.GetLabelFor(unitType);
- break;
- case DisplayUnitType displayUnitType:
- name = LabelUtils.GetLabelFor(displayUnitType);
- break;
- case UnitSymbolType symbolType:
- name = LabelUtils.GetLabelFor(symbolType);
- break;
-#endif
- case ElementType elementType:
- name = elementType.Name;
- break;
- case Element element:
- name = element.Name;
- break;
- }
-#if REVIT2025
- if (enumItem is ForgeTypeId forgeTypeId)
- {
- var label = LabelUtils.GetLabelForBuiltInParameter(forgeTypeId);
- }
-#endif
- dict.Add((T)enumItem, name);
- }
- return dict;
- }
- }
-}
diff --git a/ShrlAlgoToolkit.Revit/Assists/DMUAssist.cs b/ShrlAlgoToolkit.Revit/Assists/DMUAssist.cs
deleted file mode 100644
index a32a527..0000000
--- a/ShrlAlgoToolkit.Revit/Assists/DMUAssist.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using Autodesk.Revit.DB;
-
-namespace ShrlAlgoToolkit.Revit.Assists
-{
- ///
- /// 动态模型更新
- ///
- ///
- public static class DMUAssist
- {
- public static void AddTrigger(this IUpdater updater, Document document, ElementFilter filter, ChangeType change)
- {
- UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), document, filter, change);
- }
- }
-
- //internal class test
- //{
- // private readonly ChangeType change = null;
- // private readonly ICollection elements = null;
- // private readonly uiApplication uiApplication = null;
- // private Guid guid = new();
-
- // public void MyMethod()
-
- // {
- // var guid = new Guid();
- // Updater updater = new Updater
- // {
- // addinID = null,
- // Guid = guid
- // };
-
- // DMUAssist dynamicModel =
- // new DMUAssist(uiApplication, elements, change);
-
- // dynamicModel.UseUpdater();
- // }
- //}
-}
diff --git a/ShrlAlgoToolkit.Revit/Assists/ParameterAssist.cs b/ShrlAlgoToolkit.Revit/Assists/ParameterAssist.cs
index c97a647..a1db5fb 100644
--- a/ShrlAlgoToolkit.Revit/Assists/ParameterAssist.cs
+++ b/ShrlAlgoToolkit.Revit/Assists/ParameterAssist.cs
@@ -10,7 +10,13 @@ namespace ShrlAlgoToolkit.Revit.Assists;
public class ParameterAssist
{
-
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
private static ExternalDefinition GetSharedParameter(DefinitionFile file, string groupname, string paramname)
{
var myGroups = file.Groups;
diff --git a/ShrlAlgoToolkit.Revit/Extensions/SpatialExtensions.cs b/ShrlAlgoToolkit.Revit/Extensions/SpatialExtensions.cs
index 924a47b..0aa2330 100644
--- a/ShrlAlgoToolkit.Revit/Extensions/SpatialExtensions.cs
+++ b/ShrlAlgoToolkit.Revit/Extensions/SpatialExtensions.cs
@@ -533,7 +533,11 @@ public static class SpatialExtensions
return list;
}
-
+ ///
+ ///
+ ///
+ ///
+ ///
public static ElementOrientation GetElementOrientation(this Curve curve)
{
var num = 0.0001;
diff --git a/ShrlAlgoToolkit.Revit/ShrlAlgoToolkit.Revit.projitems b/ShrlAlgoToolkit.Revit/ShrlAlgoToolkit.Revit.projitems
index 7df76bc..9bb0a90 100644
--- a/ShrlAlgoToolkit.Revit/ShrlAlgoToolkit.Revit.projitems
+++ b/ShrlAlgoToolkit.Revit/ShrlAlgoToolkit.Revit.projitems
@@ -9,9 +9,7 @@
ShrlAlgoToolkit.Revit
-
-
diff --git a/ShrlAlgoToolkit.RevitAddins/UIRibbon/ModifyTabApp.cs b/ShrlAlgoToolkit.RevitAddins/UIRibbon/ModifyTabApp.cs
index df49854..2b47ef4 100644
--- a/ShrlAlgoToolkit.RevitAddins/UIRibbon/ModifyTabApp.cs
+++ b/ShrlAlgoToolkit.RevitAddins/UIRibbon/ModifyTabApp.cs
@@ -202,12 +202,7 @@ public class ModifyTabApp
///
private void AlignPanel(RibbonTab tab)
{
- //新建面板
- Autodesk.Windows.RibbonPanel alignElemsPanel = new() { FloatingOrientation = System.Windows.Controls.Orientation.Vertical };
-
- //面板资源
- RibbonPanelSource alignSource = new() { Id = "ID_Layout_Panel", Title = "布局" };
- alignElemsPanel.Source = alignSource;
+
//面板按钮
var alignLeftBtn = new Autodesk.Windows.RibbonButton
{
@@ -367,9 +362,14 @@ public class ModifyTabApp
ribbonRowPanel1.Items.Add(new RibbonRowBreak());
ribbonRowPanel1.Items.Add(alignBottomBtn);
+ //面板资源
+ RibbonPanelSource alignSource = new() { Id = "ID_Layout_Panel", Title = "布局" };
//布局添加到面板数据源
alignSource.Items.Add(ribbonRowPanel);
alignSource.Items.Add(ribbonRowPanel1);
+ //新建面板
+ Autodesk.Windows.RibbonPanel alignElemsPanel = new() { FloatingOrientation = System.Windows.Controls.Orientation.Vertical };
+ alignElemsPanel.Source = alignSource;
tab.Panels.Add(alignElemsPanel);
}
///
diff --git a/ShrlAlgoToolkit.sln b/ShrlAlgoToolkit.sln
index ec78f51..f5853b6 100644
--- a/ShrlAlgoToolkit.sln
+++ b/ShrlAlgoToolkit.sln
@@ -82,6 +82,4 @@ Global
ShrlAlgoToolkit.Revit\ShrlAlgoToolkit.Revit.projitems*{aa64ed67-e47e-46b1-a6f6-999a26193e57}*SharedItemsImports = 5
ShrlAlgoToolkit.Revit\ShrlAlgoToolkit.Revit.projitems*{ba8ebf4a-1aac-42a5-9bc6-e3130158c8dd}*SharedItemsImports = 5
EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- EndGlobalSection
EndGlobal