Ghi Giá Trị Shared Parameters Với GUID Trong Revit API C#

/Bài viết

    Trong bài viết trước, chúng ta đã thành công trong việc truy xuất và đọc giá trị của Shared Parameters từ các đối tượng Revit thông qua GUID. Tuy nhiên, để thực sự biến Revit thành một công cụ làm việc hiệu quả, chúng ta không chỉ cần đọc, mà còn cần khả năng ghi và cập nhật dữ liệu một cách lập trình.

    Các Bước Ghi Giá Trị Vào Shared Parameter

    Để ghi hoặc cập nhật giá trị cho một Shared Parameter trên một Element thông qua API, chúng ta sẽ thực hiện các bước sau:

    1. Mở một Transaction mới: Đây là bước bắt buộc để bắt đầu các thay đổi.
    2. Tìm kiếm Shared Parameter mục tiêu: Tương tự như việc đọc, bạn cần tìm đúng Parameter trên Element mà bạn muốn cập nhật, sử dụng GUID của nó.
    3. Kiểm tra khả năng ghi: Đảm bảo Parameter đó không phải là IsReadOnly. Một số thông số không thể chỉnh sửa được thông qua API.
    4. Đặt giá trị mới: Sử dụng các phương thức Set() phù hợp với StorageType của parameter.
    5. Kết thúc Transaction: Commit() giao dịch nếu mọi thứ thành công, hoặc RollBack() nếu có lỗi.

    Ví Dụ (C#): Cập Nhật Giá Trị Shared Parameter Bằng GUID

    Hãy cùng xem một đoạn code ví dụ minh họa cách cập nhật một Shared Parameter. Chúng ta sẽ tiếp tục sử dụng ví dụ "Mã tài sản" từ bài trước.

    using Autodesk.Revit.ApplicationServices;
    using Autodesk.Revit.Attributes;
    using Autodesk.Revit.DB;
    using Autodesk.Revit.UI;
    using Autodesk.Revit.UI.Selection;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    [Transaction(TransactionMode.Manual)]
    public class WriteSharedParameterByGuid : IExternalCommand
    {
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication uiApp = commandData.Application;
            UIDocument uiDoc = uiApp.ActiveUIDocument;
            Document doc = uiDoc.Document;
    
            // 1. Xác định GUID của Shared Parameter mục tiêu
            // Thay thế bằng GUID thực tế của Shared Parameter của bạn
            Guid targetGuid = new Guid("a1b2c3d4-e5f6-7890-1234-567890abcdef");
            string parameterName = "Mã tài sản"; // Tên gợi nhớ
    
            try
            {
                // Chọn một đối tượng trong Revit UI
                Reference pickedRef = uiDoc.Selection.PickObject(ObjectType.Element, "Vui lòng chọn một đối tượng để cập nhật thông số.");
                Element selectedElement = doc.GetElement(pickedRef);
    
                if (selectedElement == null)
                {
                    message = "Không có đối tượng nào được chọn.";
                    return Result.Cancelled;
                }
    
                // Tìm kiếm Shared Parameter trên Element đã chọn
                Parameter desiredParameter = null;
                foreach (Parameter p in selectedElement.Parameters)
                {
                    if (p.IsShared)
                    {
                        ExternalDefinition externalDef = p.Definition as ExternalDefinition;
                        if (externalDef != null && externalDef.Id == targetGuid)
                        {
                            desiredParameter = p;
                            break;
                        }
                    }
                }
    
                if (desiredParameter != null)
                {
                    // **Bắt đầu Transaction để ghi dữ liệu**
                    using (Transaction tr = new Transaction(doc, "Cập nhật Shared Parameter"))
                    {
                        tr.Start();
    
                        // Kiểm tra xem parameter có thể ghi được không
                        if (desiredParameter.IsReadOnly)
                        {
                            TaskDialog.Show("Lỗi", $"Parameter '{parameterName}' là chỉ đọc và không thể cập nhật.");
                            tr.RollBack(); // Hoàn tác giao dịch
                            return Result.Failed;
                        }
    
                        // Đặt giá trị mới tùy thuộc vào kiểu dữ liệu của parameter
                        // Cần đảm bảo giá trị mới phù hợp với StorageType của parameter
                        string newValue = "TS001-REVITAPI"; // Giá trị mới cho Shared Parameter Text
    
                        switch (desiredParameter.StorageType)
                        {
                            case StorageType.String:
                                desiredParameter.Set(newValue);
                                TaskDialog.Show("Thành công", $"Đã cập nhật '{parameterName}' của '{selectedElement.Name}' thành '{newValue}'.");
                                break;
                            case StorageType.Integer:
                                // Ví dụ: desiredParameter.Set(123);
                                TaskDialog.Show("Thông báo", $"Parameter '{parameterName}' là kiểu Integer. Hãy thay đổi code để đặt giá trị Integer.");
                                break;
                            case StorageType.Double:
                                // Ví dụ: desiredParameter.Set(1.23);
                                TaskDialog.Show("Thông báo", $"Parameter '{parameterName}' là kiểu Double. Hãy thay đổi code để đặt giá trị Double.");
                                break;
                            case StorageType.ElementId:
                                // Ví dụ: desiredParameter.Set(new ElementId(200));
                                TaskDialog.Show("Thông báo", $"Parameter '{parameterName}' là kiểu ElementId. Hãy thay đổi code để đặt giá trị ElementId.");
                                break;
                            default:
                                TaskDialog.Show("Cảnh báo", $"Không hỗ trợ kiểu dữ liệu này để cập nhật: {desiredParameter.StorageType}.");
                                break;
                        }
    
                        tr.Commit(); // Xác nhận giao dịch để lưu các thay đổi
                    }
                }
                else
                {
                    TaskDialog.Show("Thông báo", $"Không tìm thấy Shared Parameter '{parameterName}' với GUID '{targetGuid}' trên đối tượng đã chọn. " +
                                                 "Đảm bảo parameter đã được thêm vào đối tượng hoặc loại đối tượng đó.");
                }
    
                return Result.Succeeded;
            }
            catch (OperationCanceledException)
            {
                message = "Người dùng đã hủy thao tác chọn.";
                return Result.Cancelled;
            }
            catch (Exception ex)
            {
                message = "Lỗi: " + ex.Message;
                return Result.Failed;
            }
        }
    }
    
    • desiredParameter.IsReadOnly: Trước khi cố gắng ghi, luôn kiểm tra thuộc tính này. Nếu là true, bạn không thể thay đổi giá trị của parameter đó.
    • desiredParameter.Set(newValue): Phương thức này được sử dụng để gán giá trị mới cho parameter. Bạn cần đảm bảo newValue có kiểu dữ liệu phù hợp với StorageType của desiredParameter. Ví dụ:
      • desiredParameter.Set("Chuỗi văn bản mới"); cho StorageType.String
      • desiredParameter.Set(123); cho StorageType.Integer
      • desiredParameter.Set(1.23); cho StorageType.Double (Revit sử dụng đơn vị nội bộ, hãy cẩn thận khi đặt giá trị số thực)
      • desiredParameter.Set(new ElementId(12345)); cho StorageType.ElementId

    Lưu Ý Quan Trọng Khi Ghi Shared Parameters

    • Luôn đảm bảo giá trị bạn gán khớp với StorageType của Shared Parameter. Gán sai kiểu dữ liệu sẽ gây ra lỗi runtime.
    • Không bao giờ cố gắng sửa đổi mô hình Revit bên ngoài một Transaction đang hoạt động.
    • Luôn xử lý các trường hợp khi Parameter bạn tìm kiếm không tồn tại trên Element hoặc là IsReadOnly. Điều này giúp ứng dụng của bạn ổn định hơn.
    • Đối với các thông số kiểu số (Double), đặc biệt là chiều dài hoặc diện tích, Revit API làm việc với đơn vị nội bộ (internal units). Điều này thường là feet cho chiều dài. Bạn sẽ cần chuyển đổi giữa đơn vị hiển thị của người dùng và đơn vị nội bộ khi đọc/ghi các giá trị này. (Chúng ta sẽ không đi sâu vào phần này ở đây, nhưng hãy lưu ý khi làm việc với các thông số số học).