SonnyBIM
Published on

EasyRibbon - Framework Tạo Revit Ribbon UI Đơn Giản Với C# Attributes

Authors

Giới thiệu

Nếu bạn đã từng lập trình Revit Add-in, chắc hẳn bạn sẽ không xa lạ gì với việc phải viết hàng trăm dòng code chỉ để tạo một Ribbon UI đơn giản. Chính vì vậy, mình đã phát triển EasyRibbon - một framework mã nguồn mở giúp đơn giản hóa quá trình tạo Revit Ribbon UI bằng cách sử dụng C# Attributes. Thay vì viết hàng trăm dòng code, giờ đây bạn chỉ cần vài dòng attribute là có thể tạo được một giao diện Ribbon đẹp mắt và chuyên nghiệp.

Vấn đề với cách làm truyền thống

Khi tạo Revit Ribbon UI theo cách truyền thống, bạn phải:

// Traditional way - verbose and hard to maintain
public Result OnStartup(UIControlledApplication application)
{
    // Create Ribbon Tab
    string tabName = "My Tools";
    application.CreateRibbonTab(tabName);
    
    // Create Ribbon Panel
    RibbonPanel panel = application.CreateRibbonPanel(tabName, "Design Tools");
    
    // Create Push Button
    PushButtonData buttonData = new PushButtonData(
        "ColumnRebar",
        "Column Rebar",
        Assembly.GetExecutingAssembly().Location,
        "MyAddin.Commands.ColumnRebarCommand"
    );
    
    // Set button image
    buttonData.Image = new BitmapImage(new Uri("pack://application:,,,/MyAddin;component/Resources/Icons/icon16.png"));
    buttonData.LargeImage = new BitmapImage(new Uri("pack://application:,,,/MyAddin;component/Resources/Icons/icon32.png"));
    
    // Set tooltip
    buttonData.ToolTip = "Generate column reinforcement";
    
    // Add button to panel
    PushButton button = panel.AddItem(buttonData) as PushButton;
    
    // And this is just for ONE button...
    return Result.Succeeded;
}

Code như vậy rất dài dòng và khó maintain khi có nhiều buttons.

EasyRibbon - Giải pháp đơn giản và thanh lịch

Với EasyRibbon, bạn chỉ cần viết:

using EasyRibbon.UIAttributeBase;

[Tab("My Tools")]
public class MyToolsTab
{
    [Panel("Design Tools")]
    public class DesignPanel
    {
        [Button("Column Rebar",
            typeof(ColumnRebarCommand),
            Image = "/MyAddin;component/Resources/Icons/icon16.png",
            LargeImage = "/MyAddin;component/Resources/Icons/icon32.png",
            ToolTip = "Generate column reinforcement")]
        public class ColumnRebarButton;
    }
}

Chỉ vậy thôi! Code ngắn gọn, dễ đọc, dễ hiểu và dễ maintain hơn rất nhiều.

Ribbon UI mẫu được tạo bằng EasyRibbon

Tính năng nổi bật

🎯 Attribute-Based UI Definition

Định nghĩa giao diện Ribbon thông qua C# Attributes - cách tiếp cận hiện đại và declarative, giúp code clean và dễ đọc hơn.

🧩 Modular Architecture

Tổ chức nhiều add-ins thành các modules độc lập, có thể tái sử dụng. Mỗi module có thể load độc lập, debug riêng biệt, deploy linh hoạt và không ảnh hưởng lẫn nhau khi có lỗi.

🔄 Multi-Version Support

Hỗ trợ Revit từ phiên bản 2021 đến 2026 - một codebase cho nhiều phiên bản Revit.

🐛 Easy Debugging & Flexible Deployment

Debug từng module riêng lẻ hoặc tất cả cùng lúc. Triển khai tất cả modules cùng nhau hoặc từng module độc lập tùy theo nhu cầu dự án.

Hướng dẫn sử dụng

Bước 1: Cài đặt

# Clone repository
git clone https://github.com/PhanCongVuDuc/EasyRibbon.git

# Build solution trong Visual Studio
# Reference EasyRibbon.dll vào project Revit Add-in của bạn

Bước 2: Định nghĩa Ribbon UI với Attributes

EasyRibbon hỗ trợ nhiều loại UI elements:

Tab, Panel và Button

[Tab("My Tools")]
public class MyToolsTab
{
    [Panel("Design Tools")]
    public class DesignPanel
    {
        [Button("Column Rebar",
            typeof(ColumnRebarCommand),
            Image = "/MyAddin;component/Resources/Icons/icon16.png",
            LargeImage = "/MyAddin;component/Resources/Icons/icon32.png",
            ToolTip = "Generate column reinforcement",
            LongDescription = "Automatically generate reinforcement for concrete columns",
            ToolTipImage = "path/to/tooltip.png",
            ContextualHelp = "https://help-url.com")]
        public class ColumnRebarButton;
    }
}

Ví dụ đầy đủ với tất cả các tham số:

[Button("Button Text",
    typeof(CommandClass),
    Image = "path/to/16x16.png",
    LargeImage = "path/to/32x32.png",
    ToolTip = "Tooltip text",
    LongDescription = "Detailed description",
    ToolTipImage = "path/to/tooltip.png",
    ContextualHelp = "https://help-url.com")]
public class MyButton;

Stacked Buttons và Pulldown Button

// Stacked Buttons (3 buttons xếp chồng)
[StackedButton]
public class StructuralTools
{
    [Button("Beam Design", typeof(BeamCommand), ...)]
    public class BeamButton;
    
    [Button("Column Design", typeof(ColumnCommand), ...)]
    public class ColumnButton;
}

// Pulldown Button (Menu dropdown)
[PulldownButtonData("Rebar Tools", Image = "path/to/16x16.png")]
public class RebarToolsPulldown
{
    [Button("Beam Rebar", typeof(BeamRebarCommand), ...)]
    public class BeamRebar;
    
    [Button("Column Rebar", typeof(ColumnRebarCommand), ...)]
    public class ColumnRebar;
}

Bước 3: Tạo Module

using EasyRibbon.Modules;
using Autodesk.Revit.UI;

public class MyModule : IApplicationModule
{
    public string ModuleName => "My Custom Module";
    
    public void OnStartup(UIControlledApplication application)
    {
        // Create UI from attribute-defined classes
        CreateUIApp.CreateUI<MyToolsTab>(application);
    }
    
    public void OnShutdown(UIControlledApplication application)
    {
        // Cleanup if needed
    }
}

Bước 4: Tạo Application Entry Point

using Nice3point.Revit.Toolkit.External;

public class Application : ExternalApplication
{
    private readonly MyModule _module = new MyModule();
    
    public override void OnStartup()
    {
        _module.OnStartup(Application);
    }
    
    public override void OnShutdown()
    {
        _module.OnShutdown(Application);
    }
}

Xong! 🎉 Giờ bạn đã có một Revit Add-in với giao diện Ribbon đẹp mắt mà không cần viết hàng trăm dòng code.

Module System

Một trong những tính năng mạnh mẽ nhất của EasyRibbon là Module System - cho phép tổ chức nhiều add-ins thành các modules độc lập. Mỗi module có thể load độc lập, debug riêng biệt, và lỗi ở một module không ảnh hưởng đến modules khác.

Bạn có thể tạo một Master Application để load tất cả các modules cùng lúc:

using Nice3point.Revit.Toolkit.External;
using EasyRibbon.Modules;

public class MasterApplication : ExternalApplication
{
    private readonly ModuleRegistry _moduleRegistry = new ModuleRegistry();
    
    public override void OnStartup()
    {
        // Register all modules
        _moduleRegistry.RegisterModule<StructuralModule>();
        _moduleRegistry.RegisterModule<MEPModule>();
        _moduleRegistry.RegisterModule<ArchitectureModule>();
        
        // Initialize all modules at once
        _moduleRegistry.InitializeAll(Application);
    }
    
    public override void OnShutdown()
    {
        // Shutdown all modules
        _moduleRegistry.ShutdownAll(Application);
    }
}

Với cách này, bạn có thể phát triển, test và deploy từng module độc lập hoặc tất cả cùng lúc.

Cấu trúc Project

EasyRibbon/
├── EasyRibbon/                     # Core library
│   ├── UIAttributeBase/            # Attribute definitions
│   ├── Extensions/                 # Helper extensions
│   ├── Modules/                    # Module system
│   └── CreateUIApp.cs              # Main UI builder
├── EasyRibbonExample/              # Single module example
│   ├── Application.cs              # Standalone entry point
│   ├── ExampleModule.cs            # Module implementation
│   └── SonnyTab1.cs                # UI definition
└── EasyRibbonMasterExample/        # Multi-module example
    └── Application.cs              # Master application

So sánh trước và sau

Trước khi dùng EasyRibbonSau khi dùng EasyRibbon
200+ dòng code cho 5 buttonsChỉ 30-40 dòng code
Code dài dòng, khó đọcCode ngắn gọn, dễ đọc
Khó maintain và mở rộngDễ dàng maintain và mở rộng
Mất nhiều thời gianTiết kiệm thời gian đáng kể

Yêu cầu hệ thống

  • IDE: Visual Studio hoặc Rider
  • Revit: Autodesk Revit 2021 đến 2026
  • Framework: Nice3point.Revit.Toolkit
  • .NET Framework: Tùy theo phiên bản Revit

Dependencies

Examples & Demo

Repository có sẵn 2 project examples: EasyRibbonExample (single module) và EasyRibbonMasterExample (multi-module). Bạn có thể clone về và chạy thử!

Kết luận

EasyRibbon giúp đơn giản hóa quá trình phát triển Revit Add-in. Thay vì viết hàng trăm dòng boilerplate code, bạn có thể tập trung vào logic nghiệp vụ thực sự. Framework này đặc biệt hữu ích cho developers mới bắt đầu, teams làm việc với nhiều add-ins, và các projects cần maintain lâu dài.

EasyRibbon là một dự án mã nguồn mở (MIT License). Trong tương lai, mình dự định phát triển thêm SplitButton, RadioButtonGroup, UI Builder, và NuGet package.

🔗 GitHub Repository: https://github.com/PhanCongVuDuc/EasyRibbon

Nếu bạn thấy project hữu ích, hãy cho một ⭐ star trên GitHub nhé! Mọi đóng góp đều được chào đón qua GitHub Issues, Pull Requests hoặc LinkedIn.


Happy Coding with EasyRibbon! 🚀