Sdílet prostřednictvím


Přizpůsobení vytvoření a přesunutí elementu

Můžete povolit přetažení elementu do jiného prvku, a to buď z panelu nástrojů, nebo v operaci vložení nebo přesunutí. Přesunuté prvky můžete propojit s cílovými prvky pomocí zadaných relací.

Direktiva sloučení elementu (EMD) určuje, co se stane, když se jeden prvek modelu sloučí do jiného prvku modelu. K tomu dochází v těchto případech:

  • Uživatel přetáhne z panelu nástrojů do diagramu nebo obrazce.

  • Uživatel vytvoří prvek pomocí nabídky Přidat v průzkumníku nebo obrazci oddílu.

  • Uživatel přesune položku z jedné plavecké dráhy do jiné.

  • Uživatel vloží prvek.

  • Kód programu volá direktivu sloučení prvků.

I když se operace vytváření můžou lišit od operací kopírování, ve skutečnosti fungují stejným způsobem. Při přidání elementu, například z panelu nástrojů, se replikuje prototyp. Prototyp se sloučí do modelu stejným způsobem jako prvky zkopírované z jiné části modelu.

Odpovědností EMD je rozhodnout, jak se má objekt nebo skupina objektů sloučit do konkrétního umístění v modelu. Konkrétně se rozhoduje, jaké relace by se měly vytvořit, aby se sloučená skupina propojila s modelem. Můžete ho také přizpůsobit tak, aby nastavil vlastnosti a vytvořil další objekty.

Diagram showing a before and after look at a tree of elements and their reference relationships when An E M D determines how a new element is added.

EMD se vygeneruje automaticky při definování relace vkládání. Toto výchozí nastavení EMD vytvoří instanci relace, když uživatelé přidají do nadřazeného objektu nové podřízené instance. Tyto výchozí EMD můžete upravit například přidáním vlastního kódu.

Do definice DSL můžete také přidat vlastní EMD, aby uživatelé mohli přetahovat nebo vkládat různé kombinace sloučených a přijímajících tříd.

Definování direktivy sloučení elementů

Direktivy sloučení elementů můžete přidat do doménových tříd, relací domén, obrazců, spojnic a diagramů. Můžete je přidat nebo najít v Průzkumníku DSL v přijímající třídě domény. Přijímající třída je doménová třída elementu, který je již v modelu, a na který bude nový nebo zkopírovaný prvek sloučen.

Screenshot of DSL Explorer showing an E M D being added with ExampleElement selected as the Indexing class and the Applies to subclasses option checked.

Indexovací třída je doménová třída prvků, které lze sloučit do členů přijímající třídy. Instance podtřídy třídy indexování budou také sloučeny tímto EMD, pokud nenastavíte možnost Platí pro podtřídy na hodnotu False.

Existují dva druhy direktiv sloučení:

  • Direktiva Process Merge určuje relace, pomocí kterých má být nový prvek propojen do stromu.

  • Direktiva Forward Merge přesměruje nový prvek na jiný přijímající prvek, obvykle nadřazený prvek.

Vlastní kód můžete přidat do direktiv sloučení:

  • Set Pomocí vlastního přijetí přidat vlastní kód určit, zda má být konkrétní instance prvku indexování sloučena do cílového elementu. Když uživatel přetáhne z panelu nástrojů, zobrazí se "neplatný" ukazatel, pokud váš kód zakáže sloučení.

    Sloučení můžete například povolit pouze v případě, že přijímající prvek je v určitém stavu.

  • Sada Používá vlastní sloučení k přidání vlastního kódu k definování změn provedených v modelu při sloučení.

    Vlastnosti sloučeného prvku můžete například nastavit pomocí dat z nového umístění v modelu.

Poznámka:

Pokud napíšete vlastní slučovací kód, ovlivní to jenom sloučení, která se provádí pomocí tohoto EMD. Pokud existují další EMD, které sloučí stejný typ objektu, nebo pokud existuje jiný vlastní kód, který tyto objekty vytvoří bez použití EMD, nebude to mít vliv na váš vlastní slučovací kód.

Pokud chcete zajistit, aby váš vlastní kód vždy zpracovával nový prvek nebo novou relaci, zvažte definování AddRule vztahu vložení a DeleteRule třídy domény elementu. Další informace naleznete v tématu Pravidla šíření změn v rámci modelu.

Příklad: Definování EMD bez vlastního kódu

Následující příklad umožňuje uživatelům vytvořit prvek a spojnici současně přetažením z panelu nástrojů na existující obrazec. Příklad přidá EMD do definice DSL. Před touto úpravou mohou uživatelé přetáhnout nástroje do diagramu, ale ne na existující obrazce.

Uživatelé mohou také vložit prvky do jiných prvků.

Umožnění uživatelům vytvořit prvek a konektor současně

  1. Vytvořte novou DSL pomocí šablony řešení Minimal Language .

    Když spustíte tuto DSL, umožní vám vytvořit obrazce a spojnice mezi obrazci. Nový obrazec ExampleElement z panelu nástrojů nelze přetáhnout na existující obrazec.

  2. Pokud chcete uživatelům umožnit sloučení prvků s ExampleElement obrazci, vytvořte ve třídě domény novou sadu EMD ExampleElement :

    1. V Průzkumníku DSL rozbalte třídy domény. Klepněte pravým tlačítkem myši ExampleElement a klepněte na příkaz Přidat novou direktivu sloučení elementů.

    2. Ujistěte se, že je otevřené okno s podrobnostmi DSL, abyste viděli podrobnosti o novém EMD. (Nabídka: View, Other Windows, DSL Details.)

  3. Nastavte indexovací třídu v okně DSL Details, chcete-li definovat, jakou třídu prvků lze sloučit na ExampleElement objekty.

    V tomto příkladu vyberte ExampleElements, aby uživatel mohl přetáhnout nové prvky na existující prvky.

    Všimněte si, že indexovací třída se stane názvem EMD v Průzkumníku DSL.

  4. V části Sloučení procesů vytvořením propojení přidejte dvě cesty:

    • Jedna cesta propojuje nový prvek s nadřazený model. Výraz cesty, který potřebujete zadat, přejde z existujícího prvku směrem nahoru přes vztah vložení k nadřazeného modelu. Nakonec určuje roli v novém odkazu, ke kterému bude nový prvek přiřazen. Cesta je následující:

      ExampleModelHasElements.ExampleModel/!ExampleModel/.Elements

    • Druhá cesta propojuje nový prvek s existujícím elementem. Výraz cesty určuje vztah odkazu a roli, ke které bude nový prvek přiřazen. Tato cesta je následující:

      ExampleElementReferencesTargets.Sources

      Jednotlivé cesty můžete vytvořit pomocí navigačního nástroje pro cestu:

      1. V části Sloučení procesů vytvořením odkazů na cestě klikněte na <přidat cestu>.

      2. Klikněte na šipku rozevíracího seznamu napravo od položky seznamu. Zobrazí se stromové zobrazení.

      3. Rozbalte uzly ve stromu a vytvořte cestu, kterou chcete zadat.

  5. Otestujte DSL:

    1. Stisknutím klávesy F5 znovu sestavíte a spustíte řešení.

      Opětovné sestavení bude trvat déle než obvykle, protože vygenerovaný kód se aktualizuje z textových šablon tak, aby odpovídal nové definici DSL.

    2. Po spuštění experimentální instance sady Visual Studio otevřete soubor modelu dsl. Vytvořte některé ukázkové prvky.

    3. Přetáhněte z nástroje Příklad elementu na existující obrazec.

      Zobrazí se nový obrazec a je propojený s existujícím obrazcem se spojnici.

    4. Zkopírujte existující obrazec. Vyberte jiný obrazec a vložte ho.

      Vytvoří se kopie prvního obrazce. Má nový název a je propojený s druhým obrazcem pomocí spojnice.

Z tohoto postupu si všimněte následujících bodů:

  • Vytvořením direktiv sloučení elementů můžete povolit, aby libovolná třída elementu přijímala jakékoli jiné. EMD je vytvořen v přijímající doménové třídě a akceptovaná třída domény je zadána v poli Index třídy .

  • Definováním cest můžete určit, jaké odkazy se mají použít k propojení nového prvku s existujícím modelem.

    Zadané odkazy by měly obsahovat jednu relaci vložení.

  • EMD ovlivňuje vytváření z panelu nástrojů i operace vložení.

    Pokud napíšete vlastní kód, který vytváří nové prvky, můžete explicitně vyvolat EMD pomocí ElementOperations.Merge metody. Tím zajistíte, že kód provádí nové prvky do modelu stejným způsobem jako jiné operace. Další informace naleznete v tématu Přizpůsobení chování kopírování.

Příklad: Přidání vlastního kódu accept do EMD

Přidáním vlastního kódu do EMD můžete definovat složitější chování při slučování. Tento jednoduchý příklad zabrání uživateli v přidání více než pevného počtu prvků do diagramu. Příklad upraví výchozí sadu EMD, která doprovází vztah vkládání.

Napsání vlastního kódu accept, který omezí, co může uživatel přidat

  1. Vytvořte DSL pomocí šablony řešení Minimal Language . Otevřete diagram definice DSL.

  2. V DSL Exploreru rozbalte třídy domény, ExampleModel, direktivy sloučení elementů. Vyberte direktivu merge elementu, která má název ExampleElement.

    Tento EMD určuje, jak může uživatel v modelu vytvářet nové ExampleElement objekty, například přetažením z panelu nástrojů.

  3. V okně s podrobnostmi DSL vyberte Použít vlastní přijetí.

  4. Znovu sestavte řešení. Bude to trvat déle než obvykle, protože vygenerovaný kód se z modelu aktualizuje.

    Zobrazí se chyba sestavení podobná: "Company.ElementMergeSample.ExampleElement neobsahuje definici CanMergeExampleElement..."

    Je nutné implementovat metodu CanMergeExampleElement.

  5. V projektu Dsl vytvořte nový soubor kódu. Nahraďte jeho obsah následujícím kódem a změňte obor názvů na obor názvů projektu.

    using Microsoft.VisualStudio.Modeling;
    
    namespace Company.ElementMergeSample // EDIT.
    {
      partial class ExampleModel
      {
        /// <summary>
        /// Called whenever an ExampleElement is to be merged into this ExampleModel.
        /// This happens when the user pastes an ExampleElement
        /// or drags from the toolbox.
        /// Determines whether the merge is allowed.
        /// </summary>
        /// <param name="rootElement">The root element in the merging EGP.</param>
        /// <param name="elementGroupPrototype">The EGP that the user wants to merge.</param>
        /// <returns>True if the merge is allowed</returns>
        private bool CanMergeExampleElement(ProtoElementBase rootElement, ElementGroupPrototype elementGroupPrototype)
        {
          // Allow no more than 4 elements to be added:
          return this.Elements.Count < 4;
        }
      }
    }
    

    Tento jednoduchý příklad omezuje počet prvků, které lze sloučit do nadřazeného modelu. V případě zajímavějších podmínek může metoda zkontrolovat libovolné vlastnosti a odkazy přijímajícího objektu. Může také zkontrolovat vlastnosti slučujících prvků, které jsou přenášeny v objektu ElementGroupPrototype. Další informace o ElementGroupPrototypestom, viz Přizpůsobení chování kopírování. Další informace o psaní kódu, který čte model, naleznete v tématu Navigace a aktualizace modelu v kódu programu.

  6. Otestujte DSL:

    1. Stisknutím klávesy F5 znovu sestavíte řešení. Když se otevře experimentální instance sady Visual Studio, otevřete instanci vašeho DSL.

    2. Vytvořte nové prvky několika způsoby:

      • Přetáhněte z nástroje Příklad elementu do diagramu.

      • V ukázkovém Průzkumníku modelů klikněte pravým tlačítkem myši na kořenový uzel a potom klikněte na přidat nový ukázkový element.

      • Zkopírujte a vložte prvek do diagramu.

    3. Ověřte, že do modelu nemůžete přidat více než čtyři prvky. Je to proto, že všechny používají direktivu Element Merge.

Příklad: Přidání vlastního slučovacího kódu do EMD

Ve vlastním slučovacím kódu můžete definovat, co se stane, když uživatel přetáhne nástroj nebo vloží do prvku. Vlastní sloučení můžete definovat dvěma způsoby:

  1. Sada používá vlastní sloučení a zadejte požadovaný kód. Kód nahradí vygenerovaný slučovací kód. Tuto možnost použijte, pokud chcete úplně předefinovat, co sloučení dělá.

  2. Přepište metodu MergeRelate a volitelně i metodu MergeDisconnect . Chcete-li to provést, je nutné nastavit Generates Double Odvozené vlastnost třídy domény. Kód může volat vygenerovaný slučovací kód v základní třídě. Tuto možnost použijte, pokud chcete po provedení sloučení provést další operace.

    Tyto přístupy ovlivňují pouze sloučení, která se provádějí pomocí tohoto EMD. Pokud chcete ovlivnit všechny způsoby, jak lze sloučený prvek vytvořit, je alternativou definovat AddRule vztah pro vložení a třídu DeleteRule sloučené domény. Další informace naleznete v tématu Pravidla šíření změn v rámci modelu.

Přepsání mergeRelate

  1. V definici DSL se ujistěte, že jste definovali EMD, do kterého chcete přidat kód. Pokud chcete, můžete přidat cesty a definovat vlastní kód pro přijetí, jak je popsáno v předchozích částech.

  2. V diagramu DslDefinition vyberte přijímající třídu sloučení. Obvykle se jedná o třídu na zdrojovém konci vztahu vkládání.

    Například v DSL vygenerované z minimální jazyk řešení vyberte ExampleModel.

  3. V okně Vlastnosti nastavte Generates Double Odvozeno na true.

  4. Znovu sestavte řešení.

  5. Zkontrolujte obsah souboru Dsl\Generated Files\DomainClasses.cs. Vyhledejte pojmenované MergeRelate metody a prozkoumejte jejich obsah. To vám pomůže psát vlastní verze.

  6. V novém souboru kódu zapište částečnou třídu pro přijímající třídu a přepište metodu MergeRelate . Nezapomeňte volat základní metodu. Příklad:

    partial class ExampleModel
    {
      /// <summary>
      /// Called when the user drags or pastes an ExampleElement onto the diagram.
      /// Sets the time of day as the name.
      /// </summary>
      /// <param name="sourceElement">Element to be added</param>
      /// <param name="elementGroup">Elements to be merged</param>
      protected override void MergeRelate(ModelElement sourceElement, ElementGroup elementGroup)
      {
        // Connect the element according to the EMD:
        base.MergeRelate(sourceElement, elementGroup);
    
        // Custom actions:
        ExampleElement mergingElement = sourceElement as ExampleElement;
        if (mergingElement != null)
        {
          mergingElement.Name = DateTime.Now.ToLongTimeString();
        }
      }
    }
    

Psaní vlastního slučovacího kódu

  1. V Dsl\Generated Code\DomainClasses.cs zkontrolujte metody pojmenované MergeRelate. Tyto metody vytvářejí propojení mezi novým prvkem a existujícím modelem.

    Zkontrolujte také metody s názvem MergeDisconnect. Tyto metody odpojenou prvek z modelu, když se má odstranit.

  2. V průzkumníku DSL vyberte nebo vytvořte direktivu Sloučení elementů, kterou chcete přizpůsobit. V okně s podrobnostmi DSL nastavte použití vlastního sloučení.

    Když nastavíte tuto možnost, možnosti sloučení procesů a přeposlání sloučení budou ignorovány. Místo toho se použije váš kód.

  3. Znovu sestavte řešení. Bude trvat déle než obvykle, protože vygenerované soubory kódu se aktualizují z modelu.

    Zobrazí se chybové zprávy. Poklikáním na chybové zprávy zobrazíte pokyny ve vygenerovaném kódu. Tyto pokyny vás vyzve k zadání dvou metod: MergeRelateYourDomainClass a MergeDisconnectYourDomainClass.

  4. Zapište metody v částečné definici třídy do samostatného souboru kódu. Příklady, které jste prozkoumali dříve, by měly navrhnout, co potřebujete.

    Vlastní slučovací kód nebude mít vliv na kód, který vytváří objekty a relace přímo, a nebude mít vliv na jiné identifikátory EMD. Pokud chcete mít jistotu, že jsou vaše další změny implementovány bez ohledu na to, jak je prvek vytvořen, zvažte vytvoření AddRule a místo DeleteRule toho. Další informace naleznete v tématu Pravidla šíření změn v rámci modelu.

Přesměrování operace sloučení

Direktiva forward merge přesměruje cíl operace sloučení. Nový cíl je obvykle vložený nadřazený objekt počátečního cíle.

Například v dsl, který byl vytvořen pomocí šablony diagramu komponent, porty jsou vloženy do součástí. Porty se zobrazují jako malé obrazce na okraji obrazce komponenty. Uživatel vytvoří porty přetažením nástroje Port na obrazec Komponenta. Někdy ale uživatel omylem přetáhne nástroj Port na existující port místo komponenty a operace selže. To je jednoduchá chyba, pokud existuje několik existujících portů. Chcete-li uživateli pomoct vyhnout se této nepříjemnosti, můžete povolit přetažení portů na existující port, ale akci přesměrovat na nadřazenou komponentu. Operace funguje, jako by cílový prvek byl komponentou.

V řešení modelu komponent můžete vytvořit direktivu forward merge. Pokud zkompilujete a spustíte původní řešení, měli byste vidět, že uživatelé můžou přetáhnout libovolný počet prvků vstupního portu nebo výstupního portu ze sady nástrojů do prvku Komponenta. Nemůžou ale přetáhnout port na existující port. Ukazatel Nedostupný je upozorní, že tento přesun není povolený. Můžete však vytvořit direktivu forward merge, aby se port, který je neúmyslně vynechaný na existující vstupní port , přesměroval na element Component .

Vytvoření direktivy forward merge

  1. Pomocí šablony modelu komponenty vytvořte řešení Language Tools specifické pro doménu.

  2. Zobrazte průzkumníka DSL otevřením dslDefinition.dsl.

  3. V Průzkumníku DSL rozbalte třídy domény.

  4. Abstraktní doménová třída ComponentPort je základní třídou InPort i OutPort. Klepněte pravým tlačítkem na ComponentPort a potom klepněte na tlačítko Přidat novou slučovací direktivu elementu.

    Nový uzel direktivy Sloučení elementů se zobrazí pod uzlem Direktiv sloučení elementů.

  5. Vyberte uzel direktivy Sloučení elementů a otevřete okno DSL Details.

  6. V seznamu indexování třídy vyberte ComponentPort.

  7. Vyberte Přeposlat sloučení do jiné třídy domény.

  8. V seznamu výběru cesty rozbalte ComponentPort, rozbalte ComponentHasPorts a pak vyberte Komponenta.

    Nová cesta by měla vypadat přibližně takto:

    ComponentHasPorts.Component/! Komponenty

  9. Uložte řešení a pak šablony transformujte kliknutím na tlačítko úplně vpravo na panelu nástrojů Průzkumník řešení.

  10. Sestavte a spusťte řešení. Zobrazí se nová instance sady Visual Studio.

  11. V Průzkumník řešení otevřete Sample.mydsl. Zobrazí se diagram a sada nástrojů ComponentLanguage.

  12. Přetáhněte vstupní port ze sady nástrojů do jiného vstupního portu. Potom přetáhněte OutputPort na InputPort a pak do jiného outputPortu.

    Neměli byste vidět ukazatel Nedostupný a měli byste být schopni umístit nový vstupní port na existující port . Vyberte nový vstupní port a přetáhněte ho do jiného bodu komponenty.