2024-09-22 11:05:41 +08:00
using Autodesk.Revit.DB ;
using Autodesk.Revit.UI ;
using CommunityToolkit.Mvvm.ComponentModel ;
using CommunityToolkit.Mvvm.Input ;
using Nice3point.Revit.Toolkit.External.Handlers ;
2025-04-24 20:56:44 +08:00
using ShrlAlgoToolkit.Core.Assists ;
using System.Collections ;
2024-09-22 11:05:41 +08:00
using System.IO ;
using System.Text ;
using System.Windows ;
2025-02-10 20:53:40 +08:00
2025-04-24 20:56:44 +08:00
namespace ShrlAlgoToolkit.RevitAddins.RvFamily ;
2024-09-22 11:05:41 +08:00
public partial class FamilyProcessorViewModel : ObservableObject
{
[ObservableProperty]
2025-08-20 12:10:35 +08:00
private bool addCategoryui : InputAssist . Prefix ;
2024-09-22 11:05:41 +08:00
[ObservableProperty]
private bool createCategoryFolder ;
[ObservableProperty]
private IList < ElementType > familyEditCollection ;
//private readonly List<TreeModel> familyNodes = new();
[ObservableProperty]
private string findStr ;
private readonly ActionEventHandler handler ;
[ObservableProperty]
private bool isOverride = true ;
[ObservableProperty]
private int modifyNameIndex ;
[ObservableProperty]
2025-04-24 20:56:44 +08:00
[NotifyCanExecuteChangedFor(nameof(RevitAddins.RvFamily.FamilyProcessorViewModel.SaveFamiliesCommand))]
2024-09-22 11:05:41 +08:00
private string pathToSaveFamily ;
[ObservableProperty]
private string prefix ;
[ObservableProperty]
private string replaceStr ;
[ObservableProperty]
2025-04-24 20:56:44 +08:00
[NotifyCanExecuteChangedFor(nameof(RevitAddins.RvFamily.FamilyProcessorViewModel.TransmitFamilyCommand), nameof(RevitAddins.RvFamily.FamilyProcessorViewModel.SaveFamiliesCommand))]
2024-09-22 11:05:41 +08:00
private Document sourceDoc ;
[ObservableProperty]
private string suffix ;
[ObservableProperty]
2025-04-24 20:56:44 +08:00
[NotifyCanExecuteChangedFor(nameof(RevitAddins.RvFamily.FamilyProcessorViewModel.TransmitFamilyCommand))]
2024-09-22 11:05:41 +08:00
private Document targetDoc ;
//private readonly ExternalEvent saveEvent;
//private readonly SaveFamilyHandler handler;
//便于类中各处进行调用,故在此处添加字段
private readonly UIApplication uiapp ;
[ObservableProperty]
private bool view3dAsDefault ;
[ObservableProperty]
public List < Family > familyCollection = new ( ) ;
[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();
2024-10-27 00:19:48 +08:00
// //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 )
{
if ( obj is System . Windows . Window window )
{
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 )
{
var items = ( System . Collections . IList ) obj ;
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-20 12:10:35 +08:00
if ( AddCategoryui : InputAssist . Prefix )
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 ( )
{
2025-08-20 12:10:35 +08:00
NeoUI . 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;
// }
//}