using System.Collections; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; namespace ShrlAlgoToolkit.RevitAddins.RvFamily; public partial class RenameFamilyViewModel : ObservableObject { public RenameFamilyViewModel(UIApplication uiApplication) { doc = uiApplication.ActiveUIDocument.Document; allCategories = GetCategoriesFromDocument(); Collection = allCategories; //ICollectionView cv = CollectionViewSource.GetDefaultView(Categories); //cv.Filter = item => string.IsNullOrEmpty(SearchText) || // ((KeyValuePair)item).Value.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0; //TaskDialog.Show("数量", CategoriesDictionary.Count.ToString()); } //[ObservableProperty] //private List selectedBuiltInCategories; private readonly Dictionary> allCategories; //public ICollectionView CategoriesCollectionView { get; set; } private readonly Document doc; [ObservableProperty] private bool canInput; [ObservableProperty] private bool isRunning; [ObservableProperty] private bool isUsed; [ObservableProperty] private Dictionary> collection; [ObservableProperty] private int categoryCount; /// /// 列表中元素 /// [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(RevitAddins.RvFamily.RenameFamilyViewModel.ModifyNameCommand))] private List renameItems; [ObservableProperty] private string foundText; [ObservableProperty] private string prefixText; [ObservableProperty] private string replaceText; [ObservableProperty] private string searchText; [ObservableProperty] private string separator = "-"; [ObservableProperty] private string suffixText; // ReSharper disable once ConditionIsAlwaysTrueOrFalse public bool CanModify => RenameItems?.Any(item => item.IsSelected) == true; public bool? IsAllItemsSelected { get { if (RenameItems == null) { return false; } var selected = Enumerable.Select(RenameItems, item => item.IsSelected).Distinct().ToList(); return selected?.Count == 1 ? selected.Single() : null; } set { if (value.HasValue) { SelectAll(value.Value, RenameItems); OnPropertyChanged(); } } } partial void OnIsUsedChanged(bool value) { if (value) { var collector = doc.OfCollector().WhereElementIsNotElementType(); foreach (var item in RenameItems) { foreach (var id in item.Family.GetFamilySymbolIds()) { var b = collector.Any(e => e.GetTypeId() == id); if (b) { item.IsSelected = true; break; } } } } } public Dictionary> GetCategoriesFromDocument() { var dict = new FilteredElementCollector(doc) .OfClass(typeof(Family)) .Cast() .Where(f => f.FamilyCategory is { CategoryType: CategoryType.Model or CategoryType.Annotation, AllowsBoundParameters: true }) .GroupBy(f => f.FamilyCategory.Id) .ToDictionary(g => Category.GetCategory(doc, g.Key).Name, g => g.ToList()); CategoryCount = dict.Count; return dict; //foreach (BuiltInCategory builtInCategory in Enum.GetValues(typeof(BuiltInCategory))) //{ // Category category = Category.GetCategory(doc, builtInCategory); // if (category is // { // CategoryType: CategoryType.Model or CategoryType.Annotation, // AllowsBoundParameters: true // }) // { // var familyType = new FilteredElementCollector(doc) // .QueryElementsByType(typeof(Family)) // .OfCategory(builtInCategory) // .Cast() // .ToList(); // if (familyType.Any()) // { // var name = category.Name; // items.Add(builtInCategory, name); // } // } //} //CategoryCount = items.Count; //return items.OrderBy(kv => kv.Value).ToDictionary(kv => kv.Key, kv => kv.Value); } [RelayCommand(CanExecute = nameof(CanModify))] private async Task ModifyName() { await Task.Delay(1_000); ModifyFamilyName(); } /// /// 获取列表中所有条目的新名称 /// private void GetNewNames() { var selectedItems = Enumerable.Where(RenameItems, item => item.IsSelected); foreach (var renameItem in selectedItems) { var tempName = renameItem.OldFamilyName; //手动修改的新名称不处理 if (!string.IsNullOrEmpty(renameItem.NewFamilyName)) { continue; } if (!string.IsNullOrEmpty(FoundText)) { tempName = tempName.Replace(FoundText, string.IsNullOrEmpty(ReplaceText) ? string.Empty : ReplaceText); } if (!string.IsNullOrEmpty(ui:InputAssist.PrefixText)) { tempName = tempName.Insert(0, $"{ui:InputAssist.PrefixText}{Separator}"); } if (!string.IsNullOrEmpty(ui:InputAssist.SuffixText)) { tempName += $"{Separator}{ui:InputAssist.SuffixText}"; } renameItem.NewFamilyName = tempName; } } /// /// 获取重命名的条目 /// /// [RelayCommand] private void GetRenameItems(IList items) { if (items.Count == 0) { RenameItems = null!; CanInput = false; return; } List familyItems = new(); foreach (var item in items) { if (item is KeyValuePair> categoryItems) { //var familyType = new FilteredElementCollector(doc) // .QueryElementsByType(typeof(Family)) // .Cast() // .Where( // f => f.FamilyCategory.Id.IntegerValue == new ElementId(categoryItem.Key).IntegerValue // ); foreach (var family in categoryItems.Value) { RenameFamilyItem renameItem = new() { OldFamilyName = family.Name, Family = family, CategoryName = categoryItems.Key }; familyItems.Add(renameItem); } } } CanInput = familyItems.Any(); RenameItems = familyItems; //IsAllItemsSelected = true; foreach (var renameItem in RenameItems) { renameItem.PropertyChanged += (sender, args) => { //选中属性修改时,触发 if (args.PropertyName == nameof(RevitAddins.RvFamily.RenameFamilyItem.IsSelected)) { OnPropertyChanged(nameof(IsAllItemsSelected)); ModifyNameCommand.NotifyCanExecuteChanged(); if (string.IsNullOrEmpty(renameItem.NewFamilyName)) { GetNewNames(); } } //单个修改名称时 //if (args.PropertyName == nameof(RenameFamilyItem.NewFamilyName)) //{ // ModifyFamilyName(); //} }; } } /// /// 修改族名称 /// private void ModifyFamilyName() { var needToRename = Enumerable.Where(RenameItems, item => item.IsSelected); using Transaction ts = new(doc, "修改族名称"); ts.Start(); foreach (var renameItem in needToRename) { if (!string.IsNullOrEmpty(renameItem.NewFamilyName)) { renameItem.Family.Name = renameItem.NewFamilyName; renameItem.OldFamilyName = renameItem.NewFamilyName; } } ts.Commit(); } partial void OnFoundTextChanged(string value) { GetNewNames(); } partial void Onui:InputAssist.PrefixTextChanged(string value) { GetNewNames(); } partial void OnReplaceTextChanged(string value) { GetNewNames(); } partial void OnSearchTextChanged(string value) { Collection = allCategories .Where(kv => string.IsNullOrEmpty(value) || kv.Key.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) .ToDictionary(k => k.Key, v => v.Value); CategoryCount = Collection.Count; //CategoriesCollectionView.Refresh(); } partial void OnSeparatorChanged(string value) { GetNewNames(); } partial void Onui:InputAssist.SuffixTextChanged(string value) { GetNewNames(); } private static void SelectAll(bool select, IEnumerable models) { foreach (var model in models) { model.IsSelected = select; } } }