Files
ShrlAlgoToolkit/ShrlAlgoToolkit.RevitAddins/FamMaster/FamilyProcessorViewModel.cs

550 lines
19 KiB
C#
Raw Normal View History

2026-02-20 16:47:26 +08:00
using System.Collections;
2024-09-22 11:05:41 +08:00
using System.IO;
using System.Text;
using System.Windows;
2026-02-20 16:47:26 +08:00
using Autodesk.Revit.DB;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Nice3point.Revit.Toolkit.External.Handlers;
2026-02-21 16:31:24 +08:00
using ShrlAlgoToolkit.RevitAddins.Common.Assists;
2026-02-22 20:03:42 +08:00
namespace ShrlAlgoToolkit.RevitAddins.FamMaster;
2024-09-22 11:05:41 +08:00
public partial class FamilyProcessorViewModel : ObservableObject
{
[ObservableProperty]
public partial bool AddCategoryPrefix { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial bool CreateCategoryFolder { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial IList<ElementType> FamilyEditCollection { get; set; }
2024-09-22 11:05:41 +08:00
//private readonly List<TreeModel> familyNodes = new();
[ObservableProperty]
public partial string FindStr { get; set; }
2024-09-22 11:05:41 +08:00
private readonly ActionEventHandler handler;
[ObservableProperty]
public partial bool IsOverride { get; set; } = true;
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial int ModifyNameIndex { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
2026-02-24 11:34:18 +08:00
[NotifyCanExecuteChangedFor(nameof(SaveFamiliesCommand))]
public partial string PathToSaveFamily { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial string Prefix { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial string ReplaceStr { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
2026-02-24 11:34:18 +08:00
[NotifyCanExecuteChangedFor(nameof(TransmitFamilyCommand), nameof(SaveFamiliesCommand))]
public partial Document SourceDoc { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial string Suffix { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
2026-02-24 11:34:18 +08:00
[NotifyCanExecuteChangedFor(nameof(TransmitFamilyCommand))]
public partial Document TargetDoc { get; set; }
2024-09-22 11:05:41 +08:00
//private readonly ExternalEvent saveEvent;
//private readonly SaveFamilyHandler handler;
//便于类中各处进行调用,故在此处添加字段
private readonly UIApplication uiapp;
[ObservableProperty]
public partial bool View3dAsDefault { get; set; }
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public partial List<Family> FamilyCollection { get; set; } = new();
2024-09-22 11:05:41 +08:00
[ObservableProperty]
public List<Document> sourceDocsList;
[ObservableProperty]
public List<Document> targetDocsList;
public FamilyProcessorViewModel(UIApplication uiapp)
{
this.uiapp = uiapp;
handler = new ActionEventHandler();
FamilyEditCollection = uiapp.ActiveUIDocument.Document
.OfClasses(typeof(HostObjAttributes), typeof(FamilySymbol))
.Cast<ElementType>()
.ToList();
SourceDocsList = AllDocuments;
//FamilyEditCollection = uiApplication.ActiveUIDocument.Document.QueryElementTypeByType<ElementType>().Cast<ElementType>().ToList();
}
//private List<TreeModel> AddFamilyToTreeView()
//{
// List<TreeModel> familiesTree = new();
// #region 族
// if (SourceDoc == null)
// {
// return null;
// }
// var categories = SourceDoc.Settings.Categories;
// var familyCollector = SourceDoc.OfClass<Family>().Cast<Family>().ToList();
// var familySymbolCollector = SourceDoc.OfClass<FamilySymbol>().Cast<FamilySymbol>().ToList();
// //ErrorModels<ElementId> dimensionTypeId = (from ElementToMove i in new FilteredElementCollector(sourceDoc).OfClass(typeof(DimensionType)) select i.ViewId).ToList();
2024-09-22 11:05:41 +08:00
// //var elementTypes = new FilteredElementCollector(sourceDoc).OfClass(typeof(ElementType));
// //ElementClassFilter familysymbolfilter = new ElementClassFilter(typeof(FamilySymbol));
// //ElementClassFilter hostsymbolFilter = new ElementClassFilter(typeof(HostObjAttributes));
// //LogicalOrFilter andfilter = new LogicalOrFilter(familysymbolfilter, hostsymbolFilter);
// //var familiesSymbolCollector = new FilteredElementCollector(sourceDoc).WherePasses(andfilter);
// foreach (Category category in categories)
// {
// TreeModel familyCategoryNode =
// new()
// {
// //familyCategory.ViewId = category.Name;
// Name = category.Name,
// IsExpanded = false
// };
// foreach (var family in familyCollector)
// {
// if (family.FamilyCategory.Name == category.Name)
// {
// TreeModel familyNode =
// new()
// {
// //familyNode.ViewId = family.Name;
// Name = family.Name,
// IsExpanded = false,
// Parent = familyCategoryNode
// };
// familyCategoryNode.Children.Add(familyNode);
// //获取族及其族类型,作为加载对象合集
// familyNodes.Add(familyNode);
// foreach (var familySymbol in familySymbolCollector)
// {
// if (familySymbol.FamilyName == family.Name)
// {
// TreeModel familySymbolNode =
// new()
// {
// //familiesSymbolNode.ViewId = familySymbol.Name;
// Name = familySymbol.Name,
// Parent = familyNode
// };
// familyNode.Children.Add(familySymbolNode);
// }
// }
// }
// }
// if (familyCategoryNode.Children.Count != 0)
// {
// FamilyNodesList.Add(familyCategoryNode);
// }
// }
// #endregion 族
// var hostObjectCollector = new FilteredElementCollector(SourceDoc)
// .OfClass(typeof(HostObjAttributes))
// .Cast<HostObjAttributes>()
// .ToList();
// //IList<string> categoryNames = (from HostObjAttributes ele in hostObjectCollector
// // select ele.Category.Name).ToList();
// //var elementTypes = new FilteredElementCollector(sourceDoc).OfClass(typeof(ElementType));
// //ErrorModels<string> ss1 = categoryNames.Distinct().ToList();
// foreach (var obj in hostObjectCollector)
// {
// var categoryName = obj.Category.Name;
// var familyName = obj.FamilyName;
// var familySymbolName = obj.Name;
// #region categoryRegion
// TreeModel familyCategoryNode = null;
// foreach (var t in familiesTree)
// {
// if (t.ToolTip.Equals(categoryName)) //遍历是否找到相同的节点
// {
// familyCategoryNode = t; //有则传递给当前类别节点
// break;
// }
// }
// if (familyCategoryNode == null)
// {
// TreeModel t = new() { Name = categoryName, IsExpanded = false };
// familyCategoryNode = t;
// familiesTree.Add(familyCategoryNode);
// }
// #endregion categoryRegion
// #region familyRegion
// TreeModel familyNode = null;
// foreach (var t in familyCategoryNode.Children)
// {
// if (t.ToolTip.Equals(categoryName + "-" + familyName))
// {
// familyNode = t;
// break;
// }
// }
// if (familyNode == null)
// {
// TreeModel t =
// new()
// {
// Name = familyName,
// IsExpanded = false,
// Parent = familyCategoryNode
// };
// familyCategoryNode.Children.Add(t);
// familyNode = t;
// familyNodes.Add(familyNode);
// }
// #endregion familyRegion
// #region familySymbol
// TreeModel familySymbolNode = null;
// foreach (var t in familyNode.Children)
// {
// if (t.ToolTip.Equals(familyName + "-" + familySymbolName))
// {
// familySymbolNode = t;
// break;
// }
// }
// if (familySymbolNode == null)
// {
// TreeModel t =
// new()
// {
// Name = familySymbolName,
// IsExpanded = false,
// Parent = familyNode
// };
// familyNode.Children.Add(t);
// }
// #endregion familySymbol
// //TreeModel familyNode = new TreeModel();
// //familyNode.Name = obj.FamilyName;
// ////familyNode.Name = obj.FamilyName;
// //familyNode.IsExpanded = false;
// //familyNode.Parent = categoryNode;
// //categoryNode.Children.Add(familyNode);
// //familyNodes.Add(familyNode);
// ////if (obj.Name == familyNode.Name)
// ////{
// //TreeModel familiesSymbolNode = new TreeModel();
// ////familiesSymbolNode.ViewId = familySymbol.Name;
// //familiesSymbolNode.Name = obj.Name;
// //familiesSymbolNode.Parent = familyNode;
// //familyNode.Children.Add(familiesSymbolNode);
// //}
// }
// familiesTree.Sort();
// return familiesTree;
// //FamilyTreeView.UpdateLayout();
//}
[RelayCommand]
private static void Cancel(object obj)
{
2026-02-24 11:34:18 +08:00
if (obj is Window window)
2024-09-22 11:05:41 +08:00
{
window.DialogResult = false;
}
}
/// <summary>
/// 获取当前所有文档
/// </summary>
/// <returns></returns>
private List<Document> ListOfOpenedDocument()
{
var documents = new List<Document>();
foreach (Document document in uiapp.Application.Documents)
{
if (!document.IsLinked && !document.IsFamilyDocument)
{
documents.Add(document);
}
}
return documents;
}
partial void OnSourceDocChanged(Document value)
{
FamilyCollection = SourceDoc.OfClass<Family>().OfType<Family>().Where(f => f.IsEditable).ToList();
TargetDocsList = new(
AllDocuments.Where(
d =>
(d.PathName != null && SourceDoc?.PathName != null && d.PathName != SourceDoc.PathName)
|| (SourceDoc != null && d.Title != SourceDoc.Title)
|| SourceDoc == null
)
);
}
[RelayCommand(CanExecute = nameof(CanSaveFamilies))]
private void SaveFamilies(object obj)
{
2026-02-24 11:34:18 +08:00
var items = (IList)obj;
2024-09-22 11:05:41 +08:00
var collection = items.Cast<Family>();
var selectedItems = collection.ToList();
if (!selectedItems.Any())
{
return;
}
handler.Raise(_ =>
{
StringBuilder sb = new();
if (!Directory.Exists(PathToSaveFamily))
{
var dr = MessageBox.Show("路径不存在,是否创建该路径", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Information);
if (dr == MessageBoxResult.OK)
{
try
{
Directory.CreateDirectory(PathToSaveFamily);
}
catch (Exception ex)
{
ex.Message.ToLog();
MessageBox.Show("无法创建保存路径", "错误", MessageBoxButton.YesNo, MessageBoxImage.Error);
}
}
}
else
{
//FileInfo fileInfo = new FileInfo(text3);
foreach (var family in selectedItems)
{
var familyFileInfo = family.Name;
//string categoryInfo = family.Category.Name;
var directory = PathToSaveFamily + "\\";
var categoryInfo = family.FamilyCategory.Name;
if (CreateCategoryFolder)
{
directory += $"{categoryInfo}\\";
DirectoryInfo directoryInfo = new(directory);
if (!directoryInfo.Exists)
{
directoryInfo.Create();
}
}
2025-08-24 13:49:55 +08:00
if (AddCategoryPrefix)
2024-09-22 11:05:41 +08:00
{
familyFileInfo = $"({categoryInfo}){familyFileInfo}";
}
var completeDir = directory + familyFileInfo + ".rfa";
try
{
FileInfo fileInfo = new(completeDir);
if (fileInfo.Exists)
{
if (IsOverride)
{
fileInfo.Delete();
}
}
if (family.IsEditable)
{
var editFamily = SourceDoc.EditFamily(family);
if (View3dAsDefault)
{
Set3DView(editFamily);
}
editFamily.SaveAs(completeDir);
editFamily.Close(false);
}
else
{
sb.AppendLine($"{categoryInfo}-{family.Name}");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
if (!string.IsNullOrEmpty($"{sb}"))
{
MessageBox.Show($"以下族无法导出:\n{sb}", "导出错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
});
//saveEvent.Raise();
}
[RelayCommand]
private void SelectDirectory()
{
2026-01-02 17:30:41 +08:00
Melskin.Controls.VistaFolderBrowserDialog dialog = new();
2024-09-22 11:05:41 +08:00
//dialog.Description = "请选择文件路径";
//dialog.SeletcedPath = @"C:\Users\ZGG\Documents";
if (dialog.ShowDialog() == true)
{
var savePath = dialog.SelectedPath;
PathToSaveFamily = savePath;
}
}
private static void Set3DView(Document doc)
{
try
{
Transaction transaction = new(doc);
transaction.Start();
doc.GetDocumentPreviewSettings();
SaveAsOptions saveAsOptions = new();
if (doc.GetDocumentPreviewSettings().PreviewViewId.Equals(ElementId.InvalidElementId))
{
var startingViewSettings = StartingViewSettings.GetStartingViewSettings(doc);
if (!startingViewSettings.ViewId.Equals(ElementId.InvalidElementId))
{
saveAsOptions.PreviewViewId = startingViewSettings.ViewId;
}
else
{
var viewCollector = new FilteredElementCollector(doc).OfClass(typeof(View));
var viewEnum = viewCollector
.Cast<View>()
.Where(view => view.ViewType == ViewType.ThreeD && !view.IsTemplate);
var flag = true;
foreach (View view in (IEnumerable)viewEnum)
{
if (view.IsTemplate)
{
continue;
}
saveAsOptions.PreviewViewId = view.Id;
flag = false;
break;
}
if (flag)
{
foreach (
View view in (IEnumerable)
viewCollector
.Cast<View>()
.Where(viewNot3D =>
{
return viewNot3D.ViewType
is ViewType.FloorPlan
or ViewType.EngineeringPlan
or ViewType.Elevation
|| (viewNot3D.ViewType == ViewType.Section && !viewNot3D.IsTemplate);
})
)
{
if (view.IsTemplate)
{
continue;
}
saveAsOptions.PreviewViewId = view.Id;
break;
}
}
}
}
transaction.Commit();
}
catch
{
// ignored
}
}
[RelayCommand(CanExecute = nameof(CanTransmitFamilies))]
private void TransmitFamily(object obj)
{
var items = (IList)obj;
var collection = items.Cast<Family>();
var selectedItems = collection.ToList();
if (!selectedItems.Any())
{
return;
}
handler.Raise(_ =>
{
2025-04-24 20:56:44 +08:00
TargetDoc.Invoke(_ =>
2024-09-22 11:05:41 +08:00
{
CopyPasteOptions copyPasteOptions = new();
//copyPasteOptions.SetDuplicateTypeNamesHandler(copyPasteOptions.GetDuplicateTypeNamesHandler());
var ids = selectedItems.ConvertAll(f => f.Id);
ElementTransformUtils.CopyElements(SourceDoc, ids, TargetDoc, null, copyPasteOptions);
},
"传递族"
);
});
}
private List<Document> AllDocuments => ListOfOpenedDocument();
private bool CanSaveFamilies => PathToSaveFamily != null && SourceDoc != null;
private bool CanTransmitFamilies => SourceDoc != null && TargetDoc != null;
}
//public class CopyHandlerOk : IDuplicateTypeNamesHandler
//{
// public DuplicateTypeAction OnDuplicateTypeNamesFound(DuplicateTypeNamesHandlerArgs args)
// {
// return DuplicateTypeAction.UseDestinationTypes;
// }
//}
//public class CopyHandlerAbort : IDuplicateTypeNamesHandler
//{
// public DuplicateTypeAction OnDuplicateTypeNamesFound(DuplicateTypeNamesHandlerArgs args)
// {
// return DuplicateTypeAction.Abort;
// }
//}