Communauté
BIM Revit, BIM et Autodesk Construction Cloud (ACC) - Français
Bienvenue sur le forum AEC francophone dédié aux solutions BIM de la société Autodesk. Cet espace est dédié aux professionnels et passionnés du secteur de l'Architecture, de l'Ingénierie et de la Construction (AEC) qui utilisent le logiciel Revit ainsi que les plateformes collaboratives d'Autodesk (ACC et Autodesk Forma). Partagez vos connaissances, posez des questions, collaborez sur des idées, et explorez les sujets, que vous soyez architecte, ingénieur, gestionnaire de projet ou tout autre acteur de l'AEC.
annuler
Affichage des résultats de 
Afficher  uniquement  | Rechercher plutôt 
Vouliez-vous dire : 

Placement d'un élément de détail avec Visual Studio

16 RÉPONSES 16
RÉSOLU
Répondre
Message 1 sur 17
Thomas_LECUPPRE_Let_it_BIM
700 Visites, 16 Réponses

Placement d'un élément de détail avec Visual Studio

Bonjour,

J'utilise la fonction doc.PromptForFamilyInstancePlacement() pour pouvoir placer un élément de détail sur la feuille en cour.

Quand je l'utilise dans un macro Revit je n'ai aucun soucis mais c'est lorsque je transfert mon programme dans Visual Studio que j'ai un soucis. En effet, lorsque j’exécute mon code :

 

FilteredElementCollector familyCollector = new FilteredElementCollector(document);
            familyCollector.OfClass(typeof(FamilySymbol));
            FamilySymbol familySymbolToFind = null;
            

            foreach (FamilySymbol familySymbol in familyCollector)
            {
                //To search by FamilySymbol name
                //TaskDialog.Show("Revit", familySymbol.Name.ToString());
                if (familySymbol.Name == nomFamille) 
                {
                    familySymbolToFind = familySymbol;
                    TaskDialog.Show("Revit", familySymbol.Family.Name.ToString());
                } 
                //To search by Family name
                else if (familySymbol.Family.Name == nomFamille) 
                {
                    familySymbolToFind = familySymbol;
                    TaskDialog.Show("Revit", familySymbol.Family.Name.ToString());
                }
            }

            try
            {
                uiDocument.PromptForFamilyInstancePlacement(familySymbolToFind);
            }
            catch (Exception e)
            {
                string stackTrace = e.StackTrace.ToString();
                File.WriteAllText(@"E:\Erreur.txt",stackTrace);
                TaskDialog.Show("titre", stackTrace);
            }

Revit me renvoie constamment cette erreur :

à Autodesk.Revit.UI.UIDocument.PromptForFamilyInstancePlacementInternal(FamilySymbol familySymbol, PromptForFamilyInstancePlacementOptions options)
à Import_Selected_DET.Class_Import_Selected_DET.PlacerFamille(String nomFamille) dans E:\PROG_THOMAS\C#\Import_Selected_DET\Import_Selected_DET\Class_Import_Selected_DET.cs:ligne 97

 

La ligne 97 pointant sur uiDocument.PromptForFamilyInstancePlacement(familySymbolToFind);

 

Je n'arrive pas à en savoir plus sur cette erreur et comment la corriger.

16 RÉPONSES 16
Message 2 sur 17

Salut,

 

ton code est fonctionnel. Je pense que le problème provient de l'action que tu souhaite effectuer. On ne peut pas insérer un élément de détail dans une feuille. Un symbole oui mais pas un élément de détail. Ceci est une limitation Revit auquel la programmation ne peut pas contourner.

 

Je te remet ton code avec une optimisation dans le foreach. le break permet de sortir de la boucle lorsque l'on a trouvé le symbole à insérer. Cela évite d'analyser tous les éléments du projet !!!

Autre point à faire attention, tu recherche ton symbole via son nom. Le nom du symbole correspond au nom du type dans Revit. Hors plusieurs symboles peuvent avoir le même nom mais appartenir à des familles différentes. Afin de mieux cibler ta recherche, et d'éviter des erreurs je te conseille d'ajouter le nom de la famille à chercher ! Ainsi tu cible sur 2 critère et tu es certains de trouver le bon élément à insérer.

😉

[Transaction(TransactionMode.Manual)]
    public class Command : IExternalCommand
    {
        public Result Execute(ExternalCommandData extCmdData, ref string msg, ElementSet elmtSet)
        {
            UIApplication uiapp = extCmdData.Application;
            UIDocument uiDocument = uiapp.ActiveUIDocument;
            Application app = uiapp.Application;
            Document document = uiDocument.Document;

            try
            {
                FamilySymbol familySymbolToFind = null;
                string nomFamille = "Parement Brique";

                FilteredElementCollector familyCollector = new FilteredElementCollector(document);
                familyCollector.OfClass(typeof(FamilySymbol));

                foreach (FamilySymbol familySymbol in familyCollector)
                {
                    if (familySymbol.Name.Equals(nomFamille) || familySymbol.Family.Name.Equals(nomFamille))
                    {
                        familySymbolToFind = familySymbol;
                        TaskDialog.Show("Revit", familySymbol.Family.Name.ToString());
                        break;
                    }
                }

                try
                {
                    uiDocument.PromptForFamilyInstancePlacement(familySymbolToFind);
                }
                catch (Exception e)
                {
                    string stackTrace = e.StackTrace.ToString();
                    File.WriteAllText(@"E:\Erreur.txt", stackTrace);
                    TaskDialog.Show("titre", stackTrace);
                }
            }
            catch (Exception e)
            {
                msg = e.Message;
                return Result.Failed;
            }
            return Result.Succeeded;
        }
    }

 



PIRO Charles
Developer

PIRO CIE
Linkedin


Message 3 sur 17

Bonjour. Excusez moi je me suis mal exprimé, le soucis arrive alors que je souhaite placer mon élément de détail sur une vue (niveau 1 par exemple).

 

Je vous remercie déjà d'avoir optimiser mon code et oui, même si dans mon contexte deux type de famille ne peuvent avoir le même nom, je vais quand même appliquer ce double filtre.

 

J'ai donc essayé votre code et j'ai le même soucis. Revit se fige comme le montre le gif joint et je suis obliger de le fermer avec le gestionnaire des taches, aucuns message d'erreur n'est apparu.

 

 

Problème lors du placementProblème lors du placement

 

Bonne journée.

Message 4 sur 17

Salut,

 

ok, je pense comprendre le problème. Ta boite de dialog, si je ne me trompe pas est une boite de dialog modale (tu utilise showdialog pour l'afficher). Ce qui implique qu'elle est "au-dessus" de Revit.

Ce fonctionnement t'empêche de pouvoir exécuter l'action "PromptForFamilyInstancePlacement" car l'espace de travail Revit est "inactif".

Deux solutions s'offrent à toi :

- Fermer la boite de dialogue après avoir lancé l'action : "PromptForFamilyInstancePlacement"

- Utiliser une boite de dialog non modale qui restera affichée pendant l'action.

 

Attention au deuxième cas. Le fonctionnement n'est plus le même. Tu va devoir utiliser les événement Revit (Idling, DocumentChanged,..) pour gérer tes actions.

 

Bon courage !

 

😉



PIRO Charles
Developer

PIRO CIE
Linkedin


Message 5 sur 17

Je vais choisir la première solution.

J'avais déjà essayé de fermer mon Form depuis ma Class en passant par ma variable boite (qui représente mon Form) et en utilisant la méthode close() sur celle-ci Mais le résultat reste inchangé.

 

Est-il possible de fermer le Form avant la fonction ? Je suppose que non car sinon le reste du code ne s'exécuterait pas.

Mais en même temps, comment pourrais-je la fermer si j'ai déjà lancé la méthode PromptForFamily ... qui attend ma réponse dans Revit ?

 

N'y a-t-il pas moyen de rendre Revit actif directement ?

 

J'espère que mon raisonnement est compréhensible 🙂

Message 6 sur 17

Pour masquer la boite de dialogue le temps de placer le composant, tu peux utiliser la fonction "hide" :

this.Hide();
try
{
    Command.uiDocument.PromptForFamilyInstancePlacement(familySymbolToFind, opt);
}
catch (Exception ex)
{
     string stackTrace = ex.StackTrace.ToString();
     //File.WriteAllText(@"E:\Erreur.txt", stackTrace);
     TaskDialog.Show("titre", stackTrace);
}
this.ShowDialog();

 Une fois le composant placé, tu fais "echap" et la boite de dialogue se réaffiche.

 

Ensuite tu peux automatisé le "echap" via un évènement Idling.

 

😉



PIRO Charles
Developer

PIRO CIE
Linkedin


Message 7 sur 17

J'aime à croire que Revit ne veut pas de mon code 🙂

Lorsque j'utilise:

 

boite.Hide();

code

boite.ShowDialog();

 

Revit tourne en boucle jusqu'a ce que je presse Echap et que revit m'affiche :

 

PB_ShowDialog().png

 

 

 

 

 

Et lorsque j'utilise

 

boite.Hide();

code

boite.Show();

 

Revit tourne en boucle et la c'est gestionnaire, fermer car même echap n'y fait rien.

Message 8 sur 17

Bizarre !

Comment fais-tu l'appel vers ta boite de dialogue ?

 

 



PIRO Charles
Developer

PIRO CIE
Linkedin


Message 9 sur 17

public static Interface_LIB boite = new Interface_LIB(null);

Message 10 sur 17

Peux tu tester cette solution que je t'envoi.

Elle reprend les bases de ton code de placement avec une boite de dialogue très simple permettant de placer le composant.

 

PS: A utiliser avec un gabarit Archi !!



PIRO Charles
Developer

PIRO CIE
Linkedin


Message 11 sur 17

Bonjour @Thomas_LECUPPRE_Let_it_BIM 

Votre problème a-t-il été résolu? Si oui, pouvez vous nous indiquer de quelle façon pour que cela profite à la communauté, si non, pouvez vous nous apporter les précisions demandées de façon que nous puissions continuer à vous aider?

Si une des réponses à votre question résout votre problème, vous a permis de le comprendre ou contribue significativement à sa résolution, voulez vous avoir l'amabilité de cliquer sur le bouton "Accepter comme solution" en bas de la réponse? Merci.


Patrick Emin animateur de la communauté francophone


Vous avez trouvé un message utile? Alors donnez un "J'aime" à ce message!
Votre question a eu une réponse satisfaisante? Voulez vous avoir l'amabilité de cliquer sur le bouton
 APPROUVER LA SOLUTION  en bas de la réponse qui apporte une solution?
Signez notre Livre d'Or
Message 12 sur 17

Bonjour, désolé de l'absence.

J'ai pu tester votre programme et il semble fonctionner. Cependant, même si je regarde attentivement votre code, je ne remarque pas de différence avec celui que j'utilise. Me viens la question suivante.

 

Est-il possible que lorsque je charge ma famille dans Revit, celui-ci n'est pas le temps de comprendre que la famille est dans le projet que le programme lui demande déjà de la placer ?

Message 13 sur 17

Salut,

 

peux -tu faire un cas reproductible avec ton erreur et l'envoyer (joint ton fichier revit test et la famille à insérer) ?

Tu peux me l'envoyer via message privé si tu ne souhaite pas qu'il soit affiché publiquement.

 

😉

 



PIRO Charles
Developer

PIRO CIE
Linkedin


Message 14 sur 17
Charles.Piro
en réponse à: Charles.Piro

Salut @Thomas_LECUPPRE_Let_it_BIM ,

 

après analyse du fichier que tu m'a envoyé, le problème provient de ton type de boite de dialogue. Tu utilise des WindowsForm. Pour ce type de boite de dialogue, il faut que tu ferme ton formule (close()) pour pouvoir exécuter l'action.

Donc voici les 3 solutions pour résoudre ton problème :

-  Fermer le formulaire actuel à la place du Hide - Par contre il faudra relancer la commande pour ré afficher la boite de dialogue ou utiliser une boucle while (attention cela peux engendrer des erreurs de boucle).

- Utiliser une bite de dialogue non modale avec des événements (cf réponses précédentes)

- Utiliser une boite de dialogue de type WPF au lieu de WindowsForm.

 

😉



PIRO Charles
Developer

PIRO CIE
Linkedin


Message 15 sur 17

Pour ouvrir mon Form la première fois j'utilise un ShowDialog()

Après ça, je travail dans mon Form. Puis viens le moment ou je dois placer l'élément.

 

J'ai rajouté dans ma méthode qui me permet de le placer, un paramètre System.Windows.Forms.Form monForm

 

dans la suite de cette méthode, je fais donc monForm.Close();

puis j'exécute la fonction pour positionner ma famille d'élément de détail puis je fais monForm.Show();

 

Lorsque j'appel cette méthode je met "this" pour remplir le paramètre mon Form

 

private void btnImportPlace_Click(object sender, EventArgs e)
        {
            int i = this.ListDET.SelectedIndex;

            if (i == -1) { MessageBox.Show("Aucun élément n'a été selectionné", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); }
            else
            {
                thisOne = listeDETLastPathR[i];
                string nomFamille = listeDETLastName[i];
                Class_Charger_Placer_Details.InsererFamille(thisOne, nomFamille);
                Class_Charger_Placer_Details.PlacerFamille(nomFamille,this);
            }


        }

 

Spoiler alert, mon Form ne se ferme pas avec ça.

Message 16 sur 17

Cela fait un petit moment que j’avais mis ce programme de coté mais me revoilà avec une approche du problème qui est complètement différente.

 

En fait le soucis est que lorsqu'on utilise un boite.showdialog() on a du mal a faire disparaitre la fenêtre pour revenir sur l'espace de travail Revit.

 

En utilisant un boite.show() et en écrivant son code correctement (pas comme moi précédemment), nous n'avais plus de soucis pour retourner sur l'espace de travail Revit sans fermer la fenêtre.

 

Le soucis c'est qu'avec cette nouvelle méthode, dès qu'on tente d’effectuer une transaction, on est tout de suite en dehors de l'API de Revit.

 

J'ai pu voir cette solution mais je ne sais pas comment exécuter (dans l'exemple du forum) Class1.Execute

https://stackoverflow.com/questions/51750369/revit-api-cannot-run-the-external-command/63503839#6350...

Message 17 sur 17

Problème résolu avec Joshua Lemley sur stackoverflow.

 

https://stackoverflow.com/questions/63503617/revit-extenral-application-running-outside-of-api-conte...

 

Lire attentivement les commentaires des réponses.

Vous n'avez pas trouvé ce que vous recherchiez ? Posez une question à la communauté ou partagez vos connaissances.

Publier dans les forums  

Autodesk Design & Make Report