Here is my current code:
public class ContextMenuApplication : IExtensionApplication
{
private ISaveDrawingAsSectionVariantMenu _menuSaveDrawingAsSectionVariant;
public async void Initialize()
{
var apiConfig = GetAPIConfig();
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection, apiConfig);
var serviceProvider = serviceCollection.BuildServiceProvider();
_menuSaveDrawingAsSectionVariant = serviceProvider.GetRequiredService<ISaveDrawingAsSectionVariantMenu>();
_menuSaveDrawingAsSectionVariant.Attach();
}
public void Terminate()
{
_menuSaveDrawingAsSectionVariant.Detach();
}
public static void ConfigureServices(IServiceCollection services, APIConfiguration apiConfig)
{
services.AddSingleton(apiConfig);
services.AddSingleton<ISaveDrawingAsSectionVariantMenu, SaveDrawingAsSectionVariantMenu>();
services.AddSingleton<ContextMenuApplication>();
}
}
public class SaveDrawingAsSectionVariantMenu : ContextMenuBase
{
private List<ContextMenuItemModel> _menuItems = new List<ContextMenuItemModel>();
private static readonly HttpClient _client = new HttpClient();
private readonly APIConfiguration _apiConfiguration;
private readonly string _appServiceUrl = "api/app";
public SaveDrawingAsSectionVariantMenu()
{
}
public SaveDrawingAsSectionVariantMenu(APIConfiguration apiConfiguration)
{
_apiConfiguration = apiConfiguration;
_client.BaseAddress = new Uri(_apiConfiguration.BaseUrl);
}
public async void Attach()
{
await GetVariantsAsync();
//RXClass rxc = Entity.GetClass(typeof(Entity));
EventHandler onClick = new EventHandler(OnClick);
// Call the Attach method of the base class
Attach(_menuItems, onClick, ACadConstants.ContextMenu.SAVE_DRAWING_AS_SECTION_VARIANT);
}
public void Detach()
{
//RXClass rxc = Entity.GetClass(typeof(Entity));
// Call the Detach method of the base class
Detach(null);
}
// Set the OnClick method to perform an action when the menu item is selected
protected override async void OnClick(Object o, EventArgs e)
{
Document activeDoc = Application.DocumentManager.MdiActiveDocument;
if (activeDoc == null)
{
Application.ShowAlertDialog("No active document to save.");
return;
}
Editor ed = activeDoc.Editor;
if (o is MenuItem menuItem && menuItemValues.TryGetValue(menuItem, out string value))
{
var destinationFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ACadConstants.TEMP_FOLDER);
if (!Directory.Exists(destinationFolder))
{
Directory.CreateDirectory(destinationFolder);
}
string sourceFileName = Path.GetFileNameWithoutExtension(activeDoc.Name);
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string destinationFile = Path.Combine(destinationFolder, $"{sourceFileName}_{timestamp}.dwg");
try
{
using (Database db = activeDoc.Database)
{
// save the drawing to the destination folder
db.SaveAs(destinationFile, DwgVersion.Current);
}
await UploadFile(ed, destinationFile, value);
FileHelper.DeleteFile(destinationFile);
}
catch (System.Exception ex)
{
ed.WriteMessage($"\nError saving file: {ex.Message}.");
}
}
}
private async Task GetVariantsAsync()
{
var response = await _client.GetStringAsync($"{_appServiceUrl}/section-drawing/variants");
var result = JsonConvert.DeserializeObject<ResultModel<List<SectionDrawingModel>>>(response);
if (result.IsSucceed && result.Data.Any())
{
_menuItems = result.Data.Select(s => new ContextMenuItemModel(s.Id.ToString(), s.Page)).ToList();
}
}
private async Task UploadFile(Editor ed, string filePath, string variantId)
{
if (!File.Exists(filePath))
{
ed.WriteMessage($"\nFile not found.");
return;
}
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var content = new MultipartFormDataContent())
{
// read file
var fileContent = new StreamContent(stream);
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
// add file to content
content.Add(fileContent, "file", Path.GetFileName(filePath));
HttpResponseMessage response = await _client.PostAsync($"{_appServiceUrl}/azure-storage/upload?variantID={variantId}", content);
if (response.IsSuccessStatusCode)
{
ed.WriteMessage($"\nFile saved successfully.");
}
else
{
ed.WriteMessage($"\nError saving file: {response.StatusCode} - {response.ReasonPhrase}.");
}
}
}
}
}
public class ContextMenuItemModel
{
public string? Text { get; set; }
public string? Value { get; set; }
public string? Title { get; set; }
public ContextMenuItemModel(string value, string text, string? title = null)
{
Text = text;
Value = value;
Title = title ?? string.Empty;
}
}
public abstract class ContextMenuBase
{
protected static ContextMenuExtension cme;
protected static Dictionary<MenuItem, string> menuItemValues = new Dictionary<MenuItem, string>();
// Method to add ContextMenu to object
public void Attach(string menuItemText, EventHandler onClick, RXClass? entityClass = null)
{
cme = new ContextMenuExtension();
MenuItem mi = new MenuItem(menuItemText);
mi.Click += onClick;
cme.MenuItems.Add(mi);
if (entityClass is not null)
{
Application.AddObjectContextMenuExtension(entityClass, cme);
}
else
{
Application.AddDefaultContextMenuExtension(cme);
}
}
public void Attach(List<ContextMenuItemModel> menuItems, EventHandler onClick, string title, RXClass? entityClass = null)
{
cme = new ContextMenuExtension
{
Title = title
};
foreach (var menuItem in menuItems)
{
MenuItem mi = new MenuItem(menuItem.Text);
mi.Click += onClick;
cme.MenuItems.Add(mi);
menuItemValues[mi] = menuItem.Value;
}
if (entityClass is not null)
{
Application.AddObjectContextMenuExtension(entityClass, cme);
}
else
{
Application.AddDefaultContextMenuExtension(cme);
}
}
// ContextMenu removal method
public void Detach(RXClass? entityClass = null)
{
if (cme is not null)
{
if (entityClass != null)
{
Application.RemoveObjectContextMenuExtension(entityClass, cme);
}
else
{
Application.RemoveDefaultContextMenuExtension(cme);
}
cme = null;
}
}
// Abstract method to handle the event when the menu is selected
protected abstract void OnClick(Object o, EventArgs e);
}
In the code above, the GetVariantsAsync function is called to retrieve variant items and attach them to the context menu. However, these items are only bound once during the initial attachment. As a result, if the items are updated, the context menu will not reflect those changes.
I expect GetVariantsAsync to be called on every right mouse click to fetch the latest items and ensure the context menu remains up to date.
Thanks.