Continue another command without closing the current window view

Continue another command without closing the current window view

traiduong014969
Collaborator Collaborator
1,040 Views
11 Replies
Message 1 of 12

Continue another command without closing the current window view

traiduong014969
Collaborator
Collaborator

Hi all,

I've just created an interface window in AutoCAD using C# in WPF with the MVVM format. However, I've encountered some issues.

For details:

In the window view, I've created two buttons (SnapOnCommand and SnapOffCommand), which are functioning correctly. However, I would like to implement several other commands in AutoCAD without closing the window application.

Could anyone provide assistance with this matter?

// code in view 
<Button Grid.Column="0"
        Grid.Row="6"
        Content="snap on"
        Command="{Binding SnapOnCommand}"
        CommandParameter="{Binding ElementName=MainWindow}" />
<Button Grid.Column="0"
        Grid.Row="7"
        Content="snap off"
        Command="{Binding SnapOffCommand}"
        CommandParameter="{Binding ElementName=MainWindow}" />

// code in model

public class HCNModel : BaseViewModel
{

    public void DuplicateAndExplode(out List<ObjectId> explodedObjectIds)
    {
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;
        Editor ed = doc.Editor;

        explodedObjectIds = new List<ObjectId>();

        PromptEntityResult per = ed.GetEntity("\nchoose entity: ");

        if (per.Status != PromptStatus.OK)
            return;

        using (Transaction tr = db.TransactionManager.StartTransaction())
        {
            BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
            BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

            Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity;

            if (ent == null)
                return;
            Entity entCopy = ent.Clone() as Entity;

            if (entCopy == null)
                return;
            DBObjectCollection explodedObjects = new DBObjectCollection();
            entCopy.Explode(explodedObjects);
            foreach (DBObject obj in explodedObjects)
            {
                Entity explodedEntity = obj as Entity;

                if (explodedEntity != null)
                {
                    ObjectId explodedObjectId = btr.AppendEntity(explodedEntity);
                    tr.AddNewlyCreatedDBObject(explodedEntity, true);
                    explodedObjectIds.Add(explodedObjectId);
                }
            }

            tr.Commit();
        }
    }


    public void DeleteExplodedObjects(List<ObjectId> explodedObjectIds)
    {
        if (explodedObjectIds == null || explodedObjectIds.Count == 0)
        {
         
            return;
        }

        Document doc = Application.DocumentManager.MdiActiveDocument;
        if (doc == null)
        {
           
            return;
        }

        Database db = doc.Database;

        using (var tr = doc.TransactionManager.StartTransaction())
        {
            foreach (var objectId in explodedObjectIds)
            {
                try
                {
                 
                    Entity ent = tr.GetObject(objectId, OpenMode.ForWrite) as Entity;
                    if (ent != null && !ent.IsErased) 
                    {
                        
                        if (ent.OwnerId != ObjectId.Null)
                        {
                            
                            ent.Erase();
                        }
                    }
                }
                catch (System.Exception ex)
                {
                   
                    doc.Editor.WriteMessage($"\nerror: {ex.Message}");
                }
            }

            tr.Commit();
        }
    }
}

}

// code in viewmode
public class HCNViewModel : BaseViewModel
{
 private List<ObjectId> _duplicatedObjectIds = new List<ObjectId>();
 private HCNModel _HCNModel;

public HCNModel HCNModel
{
    get { return _HCNModel; }
    set { _HCNModel = value; OnPropertyChanged(nameof(HCNModel)); }
}
 public ICommand SnapOnCommand { get; set; }
 public ICommand SnapOffCommand { get; set; }
public HCNViewModel()
{
    
    HCNModel = new HCNModel();
    SnapOnCommand = new RelayCommand<object>((p) => true, (p) =>
    {
        List<ObjectId> explodedObjectIds;
        HCNModel.DuplicateAndExplode(out explodedObjectIds);

        _duplicatedObjectIds.AddRange(explodedObjectIds);
    });
    SnapOffCommand = new RelayCommand<object>((p) => true, (p) =>
    {
        Document doc = Application.DocumentManager.MdiActiveDocument;
        List<ObjectId> explodedObjectIdsToRemove = new List<ObjectId>();

        using (Transaction tr = doc.TransactionManager.StartTransaction())
        {

            foreach (var objectId in _duplicatedObjectIds)
            {
               
                Entity ent = tr.GetObject(objectId, OpenMode.ForRead) as Entity;
           
                if (ent != null && ent.OwnerId != ObjectId.Null)
                {

                    explodedObjectIdsToRemove.Add(objectId);
                }
            }

            tr.Commit();
        }
    
        HCNModel.DeleteExplodedObjects(explodedObjectIdsToRemove);

        
        foreach (var objectIdToRemove in explodedObjectIdsToRemove)
        {
            _duplicatedObjectIds.Remove(objectIdToRemove);
        }
    });
}
}
0 Likes
Accepted solutions (3)
1,041 Views
11 Replies
Replies (11)
Message 2 of 12

_gile
Consultant
Consultant

Hi,

Do you show the  interface as modal dialog (Application.ShowModalWindow) or a a modeless dialog (Application.ShowModelessWindow or using a PaletteSet)?



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 12

traiduong014969
Collaborator
Collaborator

No, I've created a button on the ribbon tab, and when I click on it, the window view appears. Then, I click a button in the window view. I want to be able to execute other commands while the window view is still open, rather than having to close it.
0 Likes
Message 4 of 12

ActivistInvestor
Mentor
Mentor

You didn't answer @_gile 's question.  

 

You need to show how you are showing the Window when you click the button on the Palette. 

 

To do anything while a window is visible you must show the window modelessly (using Application.ShowModelessWindow()). If you show the window by calling ShowModalWindow(), it blocks and will not allow you to do anything until the Window is closed.

0 Likes
Message 5 of 12

traiduong014969
Collaborator
Collaborator

This is the code to display the menu. However, I'm unsure how to modify it to enable other commands without closing the window. Could you please assist me in fixing it?

 

public class Ribbon : IExtensionApplication
{
    public void Initialize()
    {
        try
        {
            
            if (ComponentManager.Ribbon != null)
            {
               
                CreateMenu();
            }
            else
            {
               
                Autodesk.AutoCAD.Ribbon.RibbonServices.RibbonPaletteSetCreated += new EventHandler(RibbonServices_RibbonPaletteSetCreated);
            }
        }
        catch { }

    }

    private void RibbonServices_RibbonPaletteSetCreated(object sender, EventArgs e)
    {
        RibbonPaletteSet_Loaded
        Autodesk.AutoCAD.Ribbon.RibbonServices.RibbonPaletteSet.Load += new Autodesk.AutoCAD.Windows.PalettePersistEventHandler(RibbonPaletteSet_Loaded);
    }

    private void RibbonPaletteSet_Loaded(object sender, PalettePersistEventArgs e)
    {
       
        CreateMenu();
    }
//////

 

0 Likes
Message 6 of 12

ActivistInvestor
Mentor
Mentor

The code you posted is not the code that shows the window when the user clicks the button on the pallet set.

 

That is what you need to show. 

0 Likes
Message 7 of 12

traiduong014969
Collaborator
Collaborator

maybe this code. I have created to input on ribbon button

traiduong014969_0-1711298348052.png

or 

public class SendCommand : ICommand
{
event EventHandler ICommand.CanExecuteChanged
{
add { }
remove { }
}

public bool CanExecute(object parameter) { return true; }

public void Execute(object parameter)
{
if (parameter is RibbonCommandItem btn)
{

Document doc = AcadApp.DocumentManager.MdiActiveDocument;
doc.SendStringToExecute((string)btn.CommandParameter + " ", true, false, true);
}
}

 

0 Likes
Message 8 of 12

ActivistInvestor
Mentor
Mentor
Accepted solution

ShowDialog() displays a modal window that must be closed before you can do anything. If you want the window to remain open while you execute commands or something else, you have to use the ShowModelessWindow() method of the Application object.

0 Likes
Message 9 of 12

traiduong014969
Collaborator
Collaborator

es, I tested this code, and it works. However, when I click the button with the ICommand "Snapon," lines of code appear with errors.

traiduong014969_0-1711381224860.pngtraiduong014969_1-1711381495260.png

 

0 Likes
Message 10 of 12

_gile
Consultant
Consultant
Accepted solution

To be able to modify the active document from a modeless UI, you need to lock the document.

See this topic.

using (doc.LockDocument())
using (Transaction tr = db.TransactionManager.StartTransaction())
{
    // do your stuff
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 11 of 12

ActivistInvestor
Mentor
Mentor
Accepted solution

Download this file and add it to your project.

 

Then, make the following changes to your code:

 

/// change this line:
SnapOnCommand = new RelayCommand<object>((p) => true, (p) => .....

/// To this:
SnapOnCommand = new DocumentRelayCommand<object>((p) => true, (p) => ....

 

 

/// Change this line:
SnapOffCommand = new RelayCommand<object>((p) => true, (p) =>

/// To this:
SnapOffCommand = new DocumentRelayCommand<object>((p) => true, (p) =>

 

If you make these changes, then you do not have to manually lock the document, and your code will behave like a command WRT document locking and UNDO/REDO, and your command will correctly not be available when there is no active document.

0 Likes
Message 12 of 12

traiduong014969
Collaborator
Collaborator

@ActivistInvestor , @_gile . Thank you for your help

Finally this code work for me

0 Likes