using System.ComponentModel.DataAnnotations; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.UI; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Nice3point.Revit.Toolkit.External.Handlers; using Sai.Toolkit.Mvvm.Attributes; namespace Sai.RvKits.RvCivil; public partial class FloorFinishesViewModel : ObservableValidator { public FloorFinishesViewModel(IList floorTypes) { FloorTypes = floorTypes; finishesHandler = new ActionEventHandler(); } private readonly ActionEventHandler finishesHandler; //private double floorOffset; [Required] [Range(-6000, 6000, ErrorMessage = "输入偏移量值范围有误")] [NotifyCanExecuteChangedFor(nameof(PlaceFloorCommand))] [NotifyDataErrorInfo] [ObservableProperty] private double floorOffset; //[CustomValidation(typeof(FloorFinishesViewModel), nameof(ValidateFloorOffset))] //public double FloorOffset //{ // get => floorOffset; // set // { // SetProperty(ref floorOffset, value, true); // PlaceFloorCommand.NotifyCanExecuteChanged(); // } //} //自定义验证方法 //public static ValidationResult ValidateFloorOffset(string floorOffset, ValidationContext context) //{ // FloorFinishesViewModel instance = (FloorFinishesViewModel)context.ObjectInstance; // bool isValid = double.TryParse(floorOffset, out var _); // if (isValid) // { // return ValidationResult.Success; // } // return new("输入内容不是数值。"); //} [ObservableProperty] private bool rbAllRooms; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(PlaceFloorCommand))] private FloorType selectedFloorType; private bool CanPlace => SelectedFloorType != null && !HasErrors; public IList FloorTypes { get; } private IEnumerable selectedRooms; [RelayCommand(CanExecute = nameof(CanPlace))] private void PlaceFloor() { finishesHandler.Raise(app => { var uidoc = app.ActiveUIDocument; GetRoomsToPlace(uidoc); CreateFloors(uidoc); }); } public void CreateFloors(UIDocument uidoc) { var document = uidoc.Document; document.Invoke(_ => { foreach (var room in selectedRooms) { if (room != null && room.UnboundedHeight != 0.0) { //UnitFormatUtils.TryParse(document.GetUnits(), UnitType.UT_Length, FloorOffset, out double value); var option = new SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish }; var blists = room.GetBoundarySegments(option); CurveArray curveArray = new(); var loops = new List(); foreach (var bs in blists[0]) { curveArray.Append(bs.GetCurve()); } foreach (var bsList in blists) { var curveList = new List(); foreach (var bs in bsList) { curveList.Add(bs.GetCurve()); } loops.Add(CurveLoop.Create(curveList)); } var level = document.GetElement(room.LevelId) as Level; if (curveArray.Size != 0) { #if REVIT2018 || REVIT2020 document.Create.NewFloor(curveArray, SelectedFloorType, level, false) #elif REVIT2025 Floor.Create(document, loops, SelectedFloorType.Id,level.Id,false,null,0.0) #endif .get_Parameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM).Set(FloorOffset / 304.8); } } } }, "房间饰面"); } private void GetRoomsToPlace(UIDocument uidoc) { var doc = uidoc.Document; selectedRooms = RbAllRooms ? (from elem in new FilteredElementCollector(doc, doc.ActiveView.Id).OfClass(typeof(SpatialElement)) let room = elem as Room select room) : uidoc.SelectObjectsByRectangle("请框选以选择房间"); } }