Files
ShrlAlgoToolkit/ShrlAlgoToolkit.RevitAddins/FamMaster/FamilyLibraryViewModel.cs

473 lines
15 KiB
C#
Raw Normal View History

2025-04-24 20:56:44 +08:00
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
2024-09-22 11:05:41 +08:00
using Autodesk.Revit.DB;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using FuzzySharp;
using Nice3point.Revit.Toolkit.External.Handlers;
2026-02-21 16:31:24 +08:00
using ShrlAlgoToolkit.RevitAddins.Common.Assists;
using static ShrlAlgoToolkit.RevitCore.Assists.RevitFileAssist;
2025-04-24 20:56:44 +08:00
using Settings = ShrlAlgoToolkit.RevitAddins.Properties.Settings;
2026-02-22 20:03:42 +08:00
using ShrlAlgoToolkit.RevitAddins.RvFamily.FamilyLibrary;
using ShrlAlgoToolkit;
using ShrlAlgoToolkit.RevitAddins;
using ShrlAlgoToolkit.RevitAddins.RvFamily;
2024-09-22 11:05:41 +08:00
2026-02-22 20:03:42 +08:00
namespace ShrlAlgoToolkit.RevitAddins.FamMaster;
2024-09-22 11:05:41 +08:00
public partial class FamilyLibraryViewModel : ObservableObject
{
public FamilyLibraryViewModel()
{
loadFamilyHandler = new ActionEventHandler();
loadFamilySymbolHandler = new ActionEventHandler();
#if REVIT2018
FamilyPath = Settings.Default.FamilyPath_2018;
2024-09-22 11:05:41 +08:00
#elif REVIT2019
FamilyPath = Settings.Default.FamilyPath_2019;
2024-09-22 11:05:41 +08:00
#elif REVIT2020
FamilyPath = Settings.Default.FamilyPath_2020;
2024-09-22 11:05:41 +08:00
#elif REVIT2021
FamilyPath = Settings.Default.FamilyPath_2021;
2024-09-22 11:05:41 +08:00
#endif
PageSize = 20;
Initialize();
}
private readonly ActionEventHandler loadFamilyHandler;
private readonly ActionEventHandler loadFamilySymbolHandler;
[ObservableProperty]
public partial string FamilyPath { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial int PageCount { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial int PageSize { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial string RevitVersion { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial FamilyModel SelectedFamily { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial FamilyTypeDefinition SelectedSymbolType { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial List<FamilyTypeDefinition> SymbolTypes { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial bool ActiveSnackbar { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
2026-01-02 17:30:41 +08:00
public partial Melskin.Controls.Alert MessageQueue { get; set; } = new();
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial string Message { get; set; }
2024-09-22 11:05:41 +08:00
partial void OnMessageChanged(string value)
{
ActiveSnackbar = true;
}
public int FamilyCount => FamilyDataSource.Count;
/// <summary>
/// 选择树路径时的源
/// </summary>
public ObservableCollection<FamilyModel> FamilyDataSource { get; } = new();
/// <summary>
/// 单页显示的源
/// </summary>
public ObservableCollection<FamilyModel> FamilyPageListViewItems { get; set; } = new();
public ObservableCollection<TreeViewItem> FolderTreeViewItems { get; set; } = new();
[RelayCommand]
private void LvScroll(ScrollViewer scrollViewer)
{
// ReSharper disable once CompareOfFloatsByEqualityOperator
if (!isLoadingData && scrollViewer.VerticalOffset + scrollViewer.ViewportHeight == scrollViewer.ExtentHeight)
{
LoadMoreData();
}
}
private const int BatchSize = 10;
private bool isLoadingData;
/// <summary>
/// 加载目录树节点的初始化数据
/// </summary>
private void LoadInitialData()
{
isLoadingData = true;
FamilyPageListViewItems.Clear();
var size = BatchSize;
if (FamilyDataSource.Count < BatchSize)
{
size = FamilyDataSource.Count;
}
for (var i = 0; i < size; i++)
{
FamilyPageListViewItems.Add(FamilyDataSource[i]);
}
isLoadingData = false;
}
/// <summary>
/// 懒加载
/// </summary>
private void LoadMoreData()
{
isLoadingData = true;
var startIndex = FamilyPageListViewItems.Count;
var end = startIndex + BatchSize;
if (end > FamilyDataSource.Count)
{
end = FamilyDataSource.Count;
}
if (startIndex < end + 1)
{
for (var i = startIndex; i < end; i++)
{
FamilyPageListViewItems.Add(FamilyDataSource[i]);
}
}
isLoadingData = false;
}
/// <summary>
/// 递归获取路径下的所有族文件
/// </summary>
/// <param name="fullPath"></param>
private void GetFamilyFile(string fullPath)
{
DirectoryInfo dir = new(fullPath);
try
{
if (!dir.Exists)
{
return;
}
//文件系统,包含文件夹和文件
var files = dir.GetFileSystemInfos();
foreach (var fSys in files)
{
//FSys如果是文件则fileinfo不为空
if (fSys is FileInfo fileInfo)
{
if (fileInfo.Extension == ".rfa")
{
var sfInfo = new FileInfo(fileInfo.DirectoryName + "\\" + fileInfo.Name);
//RevitFileUtil.ParserRevitFile(sfInfo.FullName);
var model = new FamilyModel
{
FileInfo = sfInfo,
Path = sfInfo.FullName,
Title = Path.GetFileNameWithoutExtension(sfInfo.FullName),
ToolTip = sfInfo.Name
//RevitVersion = RevitFileUtil.RevitVersion
};
FamilyDataSource.Add(model);
}
}
else //当fileinfo为空即为文件夹向下查找
{
GetFamilyFile($"{fullPath}\\{fSys}");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// 将族加载到当前文件中
/// </summary>
[RelayCommand]
private void ImportFamily(FamilyModel model)
{
//将model的绑定数据传给外部事件
loadFamilyHandler.Raise(app =>
{
try
{
var doc = app.ActiveUIDocument.Document;
Family family;
FamilySymbol fs = null;
doc.Invoke(
_ =>
{
family = doc.GetOrLoadedFamily(model.Path);
fs = doc.GetElement(family.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;
//if (fs != null && !fs.IsActive)
//{
// fs.Activate();
//}
//if (family == null)
//{
// doc.LoadFamily(FileLibModel.Path, familyLoadOption, out family);
// fs = doc.GetElement(family.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;
//
//}
//else
//{
// MessageBox.ShowAhead("族已载入或载入失败。", "提示");
//}
},
"载入族-" + Path.GetFileNameWithoutExtension(model.Path)
);
if (fs != null && app.ActiveUIDocument.CanPlaceElementType(fs))
{
app.ActiveUIDocument.PromptForFamilyInstancePlacement(fs);
}
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException) { }
catch (Exception e)
{
Message = e.Message;
e.Message.ToLog();
}
});
}
[RelayCommand]
private void ImportFamilySymbol()
{
if (SelectedFamily == null || SelectedSymbolType == null)
{
return;
}
loadFamilySymbolHandler.Raise(app =>
{
var uidoc = app.ActiveUIDocument;
var doc = uidoc.Document;
//当前选择的族类型
FamilySymbol fs = null;
if (SelectedSymbolType.Name == null)
{
return;
}
doc.Invoke(
_ =>
{
var fam = doc.GetOrLoadedFamily(SelectedFamily.Path);
doc.Regenerate();
//if (fam == null)
//{
// doc.LoadFamilySymbol(FamilyPath, FamilySymbolName, out fs);
//}
//else
//{
var x = fam.GetFamilySymbolIds()
.FirstOrDefault(id => doc.GetElement(id).Name == SelectedSymbolType.Name);
fs = doc.GetElement(x) as FamilySymbol;
//}
if (fs?.IsActive == false)
{
fs.Activate();
}
},
"载入族-" + Path.GetFileNameWithoutExtension(SelectedFamily.Path) + " 类型:" + SelectedSymbolType.Name
);
try
{
if (fs != null && uidoc.CanPlaceElementType(fs))
{
app.ActiveUIDocument.PromptForFamilyInstancePlacement(fs);
}
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException) { }
catch (Exception e)
{
e.Message.ToLog();
}
});
}
private void Initialize()
{
PopulateTreeView(FamilyPath);
GetFamilyFile(FamilyPath);
//CurrentPageIndex = 0;
LoadInitialData();
//PageCount = GetPageCount();
//PageOrderNumberCollection = GetOrderIntCollection();
//CollectionViewSource.GetDefaultView(FamilyPageListViewItems);
}
[RelayCommand]
private static void LocationFamilyFile(object obj)
{
if (obj is FamilyModel familyInfo)
{
2026-02-21 16:31:24 +08:00
Common.Assists.WinDialogAssist.OpenFolderAndSelectFile(familyInfo.Path);
2024-09-22 11:05:41 +08:00
}
}
[RelayCommand]
private void LvSelectionChanged(object obj)
{
if (obj is FamilyModel familyInfo)
{
2025-07-11 09:20:23 +08:00
var assist = new RevitFileAssist(familyInfo.Path);
SymbolTypes = assist.SymbolTypes;
SelectedSymbolType = SymbolTypes.FirstOrDefault();
RevitVersion = assist.RevitVersion;
2024-09-22 11:05:41 +08:00
}
}
/// <summary>
/// 绑定TreeView数据源.
/// </summary>
/// <param name="path">The Path<see cref="string" />.</param>
private void PopulateTreeView(string path)
{
FolderTreeViewItems?.Clear();
var info = new DirectoryInfo(path);
if (!info.Exists)
{
return;
}
var rootNode = new TreeViewItem { Header = info.Name, Tag = info.FullName };
2025-04-24 20:56:10 +08:00
/* ShrlAlgoToolkit.RevitAddins (net481)
2024-09-22 11:05:41 +08:00
:
SubDirectories(info.GetDirectories(), rootNode);
:
FamilyLibraryViewModel.SubDirectories(info.GetDirectories(), rootNode);
*/
SubDirectories(info.GetDirectories(), rootNode);
//dirTree.DataContext = rootNode;
FolderTreeViewItems!.Add(rootNode);
rootNode.IsExpanded = true;
}
[RelayCommand]
private void SearchFamily(object obj)
{
//ListViewItem foundItem =
// textListView.FindItemWithText(searchBox.Text, false, 0, true);
//if (foundItem != null)
//{
// textListView.TopItem = foundItem;
//}
//Func<string, bool> searchFunc = BreakCurve;
//Task<bool> task = new Task<bool>(() => BreakCurve(obj.ToString()));
//task.Start();
//await task;
if (string.IsNullOrEmpty(obj.ToString()))
{
LoadInitialData();
//FamilyPageListViewItems.Clear();
//itemsLoaded.ForEach(item => FamilyPageListViewItems.Add(item));
}
else
{
//itemsLoaded.Clear();
//FamilyPageListViewItems.ForEach(item => itemsLoaded.Add(item));
FamilyPageListViewItems.Clear();
foreach (var item in FamilyDataSource)
{
if (Fuzz.PartialRatio(item.Title, obj.ToString()) > 70)
2024-09-22 11:05:41 +08:00
{
FamilyPageListViewItems.Add(item);
}
//if (item.Title.Contains(obj.ToString()))
//{
//}
}
}
}
/// <summary>
/// 选择树状节点
/// </summary>
/// <param name="obj"></param>
[RelayCommand]
private void SelectDirTreeNode(object obj)
{
//e.OriginalSource 就是TreeViewItem对象你可以将其保存到窗体类的某个私有字段中或者直接使用它如下所示
FamilyDataSource.Clear();
if (obj is TreeViewItem selectedItem)
{
GetFamilyFile(selectedItem.Tag.ToString());
}
LoadInitialData();
SymbolTypes = null;
}
/// <summary>
/// 路径选择.
/// </summary>
[RelayCommand]
private void SelectPath()
{
2026-01-02 17:30:41 +08:00
var dialog = new Melskin.Controls.VistaFolderBrowserDialog();
2024-09-22 11:05:41 +08:00
if (dialog.ShowDialog() == true)
{
try
{
#if REVIT2018
Settings.Default.FamilyPath_2018 = dialog.SelectedPath;
#elif REVIT2019
Settings.Default.FamilyPath_2019 = dialog.SelectedPath;
#elif REVIT2020
2025-07-11 09:20:23 +08:00
Settings.Default.FamilyPath_2020 = dialog.SelectedPath;
2024-09-22 11:05:41 +08:00
#elif REVIT2021
Settings.Default.FamilyPath_2021 = dialog.SelectedPath;
#endif
PopulateTreeView(dialog.SelectedPath);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
/// <summary>
/// 递归添加目录结构到TreeView根节点.
/// </summary>
/// <param name="subDirs">.</param>
/// <param name="nodeToAddTo">根节点.</param>
private static void SubDirectories(DirectoryInfo[] subDirs, TreeViewItem nodeToAddTo)
{
//父节点
foreach (var subDir in subDirs)
{
var aNode = new TreeViewItem { Header = subDir.Name, Tag = subDir.FullName };
//获取子目录
var subSubDirs = subDir.GetDirectories();
if (subSubDirs.Length != 0)
{
2025-04-24 20:56:10 +08:00
/* ShrlAlgoToolkit.RevitAddins (net481)
2024-09-22 11:05:41 +08:00
:
SubDirectories(subSubDirs, aNode);
:
FamilyLibraryViewModel.SubDirectories(subSubDirs, aNode);
*/
SubDirectories(subSubDirs, aNode);
}
nodeToAddTo.Items.Add(aNode);
}
}
}