seems postable command usage is quite limited, for instance
1) can only send warning message instead of disable command?
2) OOTB duplicate view will name that duplicated view w/ suffix Copy 1, is it possible to name it differently?
Solved! Go to Solution.
seems postable command usage is quite limited, for instance
1) can only send warning message instead of disable command?
2) OOTB duplicate view will name that duplicated view w/ suffix Copy 1, is it possible to name it differently?
Solved! Go to Solution.
Solved by Sean_Page. Go to Solution.
Regarding your question 2, you could react to the new view creation and rename it afterwards in an additional step, either using DMU or the document changed event.
Regarding your question 2, you could react to the new view creation and rename it afterwards in an additional step, either using DMU or the document changed event.
right, i'll give it a try, thanks Jeremy!
by the way, don't know if i can use ElementTypeDuplicated Event? i assume view duplicating is instance based operation, isn't it?
right, i'll give it a try, thanks Jeremy!
by the way, don't know if i can use ElementTypeDuplicated Event? i assume view duplicating is instance based operation, isn't it?
i did a quick test using document changed event, seems i cannot start transaction in order to change view name, did i miss something?
public void AppDocumentChanged(object sender, Autodesk.Revit.DB.Events.DocumentChangedEventArgs args)
{
ICollection<ElementId> views = new FilteredElementCollector(doc).OfClass(typeof(View)).ToElementIds();
ICollection<ElementId> ids = args.GetAddedElementIds();
foreach (ElementId id in ids)
if (views.Contains(id))
{
Element e = doc.GetElement(id);
string name = Regex.Replace(e.Name, @" Copy 1", "_zn"); // name changed successfully
using (Transaction tx = new Transaction(doc))
{
tx.Start("renameTransaction");
try
{
e.Name = name;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
tx.Commit();
}
}
}
i did a quick test using document changed event, seems i cannot start transaction in order to change view name, did i miss something?
public void AppDocumentChanged(object sender, Autodesk.Revit.DB.Events.DocumentChangedEventArgs args)
{
ICollection<ElementId> views = new FilteredElementCollector(doc).OfClass(typeof(View)).ToElementIds();
ICollection<ElementId> ids = args.GetAddedElementIds();
foreach (ElementId id in ids)
if (views.Contains(id))
{
Element e = doc.GetElement(id);
string name = Regex.Replace(e.Name, @" Copy 1", "_zn"); // name changed successfully
using (Transaction tx = new Transaction(doc))
{
tx.Start("renameTransaction");
try
{
e.Name = name;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
tx.Commit();
}
}
}
I do not believe you can produce a Transaction during this event. It is a read only event according to the docs.
https://www.revitapidocs.com/2015/988dd6cf-fcaa-85d2-622d-c50f13917a13.htm
That is why DMU is so nice, it happens in a transaction already so no need to start another one.
I do not believe you can produce a Transaction during this event. It is a read only event according to the docs.
https://www.revitapidocs.com/2015/988dd6cf-fcaa-85d2-622d-c50f13917a13.htm
That is why DMU is so nice, it happens in a transaction already so no need to start another one.
thanks spage, can you elaborate on Command Binding thing to disable / give warning? yes, i'll try DMU later as suggested by Jeremy too
thanks spage, can you elaborate on Command Binding thing to disable / give warning? yes, i'll try DMU later as suggested by Jeremy too
good to know that document changed event is read only, perhaps factory should provide us w/ document changing event too?
i skipped {} as only one if statement here, well, not good practice, thanks again
good to know that document changed event is read only, perhaps factory should provide us w/ document changing event too?
i skipped {} as only one if statement here, well, not good practice, thanks again
See here.
thanks spage, works great! what if i want to give warning only and continue that command in OOTB way?
thanks spage, works great! what if i want to give warning only and continue that command in OOTB way?
You would need to Remove the command binding after the warning and the use a PostCommand to call the initial CommandId.
You can also use Idle handlers to create the binding again if you want it to happen every time and not just the first time.
You would need to Remove the command binding after the warning and the use a PostCommand to call the initial CommandId.
You can also use Idle handlers to create the binding again if you want it to happen every time and not just the first time.
right, i need to use idle stuff to make sure it works every time, thanks.
right, i need to use idle stuff to make sure it works every time, thanks.
hi spage, for idle event, which scope should i put into, app or cmd? if i put @ app scope i.e. startup then it's one time only, if i put @ cmd scope then how can i use OOTB import command instead of addin command?
hi spage, for idle event, which scope should i put into, app or cmd? if i put @ app scope i.e. startup then it's one time only, if i put @ cmd scope then how can i use OOTB import command instead of addin command?
So I have it in the Application level.
1. On Startup Biding and capturing the application for later use.
public Result OnStartup(UIControlledApplication application)
{
ControlID.application = application;
AddCommandBindings(application, "ID_INPLACE_COMPONENT");
return Result.Succeeded;
}
2. Add the Command Binding and the Method to call when it captures the command.
private Result AddCommandBindings(UIControlledApplication application, string name)
{
RevitCommandId rCommandId = RevitCommandId.LookupCommandId(name);
if (rCommandId.CanHaveBinding)
{
try
{
if (name == "ID_INPLACE_COMPONENT")
{
application.CreateAddInCommandBinding(rCommandId).Executed += new EventHandler<ExecutedEventArgs>(this.DisableCommand);
}
}
catch
{
MessageBox.Show("Command " + name + " is already bound.");
}
}
return Result.Succeeded;
}
3. This is the Method the CommandBinding calls when fired
private void DisableCommand(object sender, ExecutedEventArgs args)
{
ControlID.postCommand = args.CommandId.Name;
using (Forms.RevitPostCommandForm rpc = new Forms.RevitPostCommandForm())
{
if (rpc.ShowDialog() == DialogResult.OK)
{
UIDocument uiDoc = new UIDocument(args.ActiveDocument);
uiDoc.Application.RemoveAddInCommandBinding(args.CommandId);
uiDoc.Application.PostCommand(args.CommandId);
ControlID.application.Idling += new EventHandler<IdlingEventArgs>(InPlaceComponent_Idling);
}
}
}
4. Use the associated idling event to Add the command binding back after it has fired the second time.
private void InPlaceComponent_Idling(object sender, IdlingEventArgs args)
{
AddCommandBindings(ControlID.application, "ID_INPLACE_COMPONENT");
ControlID.application.Idling -= InPlaceComponent_Idling;
}
public static class ControlID
{
public static UIControlledApplication application { get; set; }
}
So I have it in the Application level.
1. On Startup Biding and capturing the application for later use.
public Result OnStartup(UIControlledApplication application)
{
ControlID.application = application;
AddCommandBindings(application, "ID_INPLACE_COMPONENT");
return Result.Succeeded;
}
2. Add the Command Binding and the Method to call when it captures the command.
private Result AddCommandBindings(UIControlledApplication application, string name)
{
RevitCommandId rCommandId = RevitCommandId.LookupCommandId(name);
if (rCommandId.CanHaveBinding)
{
try
{
if (name == "ID_INPLACE_COMPONENT")
{
application.CreateAddInCommandBinding(rCommandId).Executed += new EventHandler<ExecutedEventArgs>(this.DisableCommand);
}
}
catch
{
MessageBox.Show("Command " + name + " is already bound.");
}
}
return Result.Succeeded;
}
3. This is the Method the CommandBinding calls when fired
private void DisableCommand(object sender, ExecutedEventArgs args)
{
ControlID.postCommand = args.CommandId.Name;
using (Forms.RevitPostCommandForm rpc = new Forms.RevitPostCommandForm())
{
if (rpc.ShowDialog() == DialogResult.OK)
{
UIDocument uiDoc = new UIDocument(args.ActiveDocument);
uiDoc.Application.RemoveAddInCommandBinding(args.CommandId);
uiDoc.Application.PostCommand(args.CommandId);
ControlID.application.Idling += new EventHandler<IdlingEventArgs>(InPlaceComponent_Idling);
}
}
}
4. Use the associated idling event to Add the command binding back after it has fired the second time.
private void InPlaceComponent_Idling(object sender, IdlingEventArgs args)
{
AddCommandBindings(ControlID.application, "ID_INPLACE_COMPONENT");
ControlID.application.Idling -= InPlaceComponent_Idling;
}
public static class ControlID
{
public static UIControlledApplication application { get; set; }
}
thanks spage, works great! except that i have to click OK twice, means that DisableCommand being executed twice, i assume it cannot be avoided because that same command being posted again, perhaps if i missed something?
thanks spage, works great! except that i have to click OK twice, means that DisableCommand being executed twice, i assume it cannot be avoided because that same command being posted again, perhaps if i missed something?
I am not somewhere I can test, but I think the Postcommand is queued until after all the other code runs, which means the Idling event is actually firing first. Maybe a Thread.Sleep(2000) in the Idling will give the PostCommand a chance to fire. Not positive on that.
I am not somewhere I can test, but I think the Postcommand is queued until after all the other code runs, which means the Idling event is actually firing first. Maybe a Thread.Sleep(2000) in the Idling will give the PostCommand a chance to fire. Not positive on that.
i did quick test, no, doesn't work, just delayed.
i did quick test, no, doesn't work, just delayed.
Looking back at my code which is working for me, the only thing I see is that I have the idler handler BEFORE the post command.
private void DisableCommand(object sender, ExecutedEventArgs args)
{
ControlID.postCommand = args.CommandId.Name;
using (Forms.RevitPostCommandForm rpc = new Forms.RevitPostCommandForm())
{
if (rpc.ShowDialog() == DialogResult.OK)
{
UIDocument uiDoc = new UIDocument(args.ActiveDocument);
uiDoc.Application.RemoveAddInCommandBinding(args.CommandId);
ControlID.application.Idling += new EventHandler<IdlingEventArgs>(InPlaceComponent_Idling);
uiDoc.Application.PostCommand(args.CommandId);
}
}
}
Looking back at my code which is working for me, the only thing I see is that I have the idler handler BEFORE the post command.
private void DisableCommand(object sender, ExecutedEventArgs args)
{
ControlID.postCommand = args.CommandId.Name;
using (Forms.RevitPostCommandForm rpc = new Forms.RevitPostCommandForm())
{
if (rpc.ShowDialog() == DialogResult.OK)
{
UIDocument uiDoc = new UIDocument(args.ActiveDocument);
uiDoc.Application.RemoveAddInCommandBinding(args.CommandId);
ControlID.application.Idling += new EventHandler<IdlingEventArgs>(InPlaceComponent_Idling);
uiDoc.Application.PostCommand(args.CommandId);
}
}
}
thanks spage, still doesn't work, the only difference is that i used window message box
DialogResult result = MessageBox.Show("click OK to continue importing but your action will be logged", "BIM & DD", MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
{
uiApp.RemoveAddInCommandBinding(arg.CommandId);
uiApp.Idling += new EventHandler<IdlingEventArgs>(OnIdling);
uiApp.PostCommand(arg.CommandId);
}
thanks spage, still doesn't work, the only difference is that i used window message box
DialogResult result = MessageBox.Show("click OK to continue importing but your action will be logged", "BIM & DD", MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
{
uiApp.RemoveAddInCommandBinding(arg.CommandId);
uiApp.Idling += new EventHandler<IdlingEventArgs>(OnIdling);
uiApp.PostCommand(arg.CommandId);
}
Can't find what you're looking for? Ask the community or share your knowledge.