Using Blazor Context Menu

Posted 2 years ago by DPrescott
Edited 2 years ago
0

Hey guys,

My coworker and I are building a grid-based application as our standing HMI for job sites. We use SVGs to draw out a square by square grid, that has different types of "tiles" or squares. We have tiles for Locations (a physical pallet stand in a system), our vehicles that drive across the system (called Rovers), a tile for Pallets, so we know where they are stored within our system, and VRCs (vertical reciprocating conveyors). 

Each tile is rich with information that we need to use, and we are trying to create a context menu that we can use on right click, to initiate various actions such as moving a vehicle, disabling locations in the software, or adding/removing pallets when necessary from the system.

Currently, we were able to successfully implement a context menu that works very well for every tile, and gives us exactly what we want, but by binding a context menu to every individual tile, the draw time increased drastically for the application. By making a top level context menu, things sped up greatly, but now we are having the issue of customizing the menu based on what type of "tile" was clicked. By having it assigned to each individual location, when we use the "zoom" function to hone in on a specific area of locations, every context menu ends up being reassigned, and it slows down the performance greatly, since we essentially have to redraw every square at a different width/height based on the zoom. Everything works, but slowly.

Here is a code block for the SVG we are using to create and customize our grid. And here is the working but "slow" implementation of our context menu (currently commented out).

What do you guys think we should do? I have seen some ideas surrounding only drawing the "blocks" that are present within the current "scroll" pane, but have no idea how to implement this.

It may be possible we need to use a "ViewBox" for our zoom instead, but we had trouble implementing this because we have 3 "sticky" headers we use. This helps us see the grid/column numbers as we scroll along the graphic, and all sorts of weird things happened when using a ViewBox, such as the grid not changing size, but instead just the total width/height of the scrollable area. When zooming in, it just starts cutting off the grid, rather than resizing it.

 

<div style="zoom:@zoom">
        <div class="grid">
            <svg id="systemGrid" height="@(maxHeight + 20)" width="@(maxWidth + 20)" @oncontextmenu:preventDefault>

                @foreach (var location in currentLocations)
                {
                    var xCoord = (location.X_Coord * SquareDimensions) + 20;
                    var yCoord = (location.Y_Coord * SquareDimensions) + 20;
                    string gridBrush = "";
                    var labelXPosition = (SquareDimensions - (SquareDimensions * .75)) / 2;

                    foreach (var type in locationTypes)
                    {
                        @if (type.TypeID == location.TypeID)
                        {
                            var trimmedBrush = type.brush.Trim();
                            @if (type.TypeDescription == "BlankDefaultProfile")
                            {
                                gridBrush = "#FFFFFF";
                            }
                            //Chech if color is of type RGB, if so convert to hex
                            else if (type.brush.Substring(0, 1) == "R")
                            {
                                string[] split;
                                int r;
                                int g;
                                int b;

                                //extract rgb values seperated by comma
                                split = type.brush.Split(new char[] { ',' });
                                r = int.Parse(split[1]);
                                g = int.Parse(split[2]);
                                b = int.Parse(split[3]);

                                gridBrush = _functions.ConvertRGBtoHex(r, g, b);
                            }

                            else if (trimmedBrush.Substring(0, 1) == "#")
                            {
                                gridBrush = String.Concat("#", trimmedBrush.Substring(3, 6));
                            }

                            @if (type.TypeID == 14)
                            {
                                var test = type.brush;
                                var test2 = gridBrush;
                            }

                            //Main Grid

                            @if (location.StorageLaneID != "")
                            {
                                @*<ContextMenuTrigger WrapperTag="g" MenuId="storageMenu">*@
                                    <g>
                                        <svg id="@location.ID" tabindex="0" x="@xCoord" y="@yCoord" height="@SquareDimensions" width="@SquareDimensions" @onkeydown="Select" @oncontextmenu:preventDefault>
                                            <rect height="100%" width="100%" fill="@gridBrush" stroke="black" stroke-width=".5" onclick="" class="location"></rect>

                                            <title class="tooltip">@location.VRCDeviceID&#13;@location.ID&#13;@type.TypeDescription&#13;</title>
                                        </svg>
                                    </g>
                                @*</ContextMenuTrigger>*@
                            }
                            else
                            {
                                @*<ContextMenuTrigger WrapperTag="g" MenuId="locationMenu">*@
                                    <g>
                                        <svg id="@location.ID" tabindex="0" x="@xCoord" y="@yCoord" height="@SquareDimensions" width="@SquareDimensions" @ondblclick="() => modal.Open()" @oncontextmenu:preventDefault>
                                            <rect height="100%" width="100%" fill="@gridBrush" stroke="black" stroke-width=".5" onclick="" class="location"></rect>

                                            <title class="tooltip">@location.VRCDeviceID&#13;@location.ID&#13;@type.TypeDescription&#13;</title>

                                            @if (location.OneWayRight == true)
                                            {
                                                <svg><text x="35" y="28" fill="black" font-size="14">&rarr;</text></svg>
                                            }
                                            @if (location.OneWayLeft == true)
                                            {
                                                <svg><text x="1" y="28" fill="black" font-size="14">&larr;</text></svg>
                                            }
                                            @if (location.OneWayDown == true)
                                            {
                                                <svg><text x="21" y="45" fill="black" font-size="14">&darr;</text></svg>
                                            }
                                            @if (location.OneWayUp == true)
                                            {
                                                <svg><text x="21" y="12" fill="black" font-size="14">&uarr;</text></svg>
                                            }
                                            @if (location.QueueIndex > 0)
                                            {
                                                <svg>
                                                    <rect width="36%" height="30%" x="3" y="32" fill="none" stroke="black" stroke-width=".5"></rect>
                                                    <text x="5" y="44" font-size="10">Q@(location.QueueIndex)</text>
                                                    <title>Queue Index</title>
                                                </svg>
                                            }
                                            @if (location.UnloadedRoverOnly)
                                            {
                                                <svg>
                                                    <rect width="23%" height="30%" x="3" y="32" fill="none" stroke="black" stroke-width=".5"></rect>
                                                    <text x="5" y="44" font-size="10">U</text>
                                                    <title>Unloaded Rover Only</title>
                                                </svg>
                                            }
                                            @if (location.CycleLocation)
                                            {
                                                <svg>
                                                    <rect width="23%" height="30%" x="3" y="32" fill="none" stroke="black" stroke-width=".5"></rect>
                                                    <text x="5" y="44" font-size="10">C</text>
                                                    <title>Cycle Location</title>
                                                </svg>
                                            }
                                            @if (location.AdditionalProperties == "OC")
                                            {
                                                <svg>
                                                    <rect width="36%" height="30%" x="17" y="32" fill="none" stroke="black" stroke-width=".5"></rect>
                                                    <text x="18" y="44" font-size="10">OC</text>
                                                    <title>Opportunistic Charger</title>
                                                </svg>
                                            }
                                            @if (location.AdditionalProperties == "SlowZone")
                                            {
                                                <svg>
                                                    <rect width="36%" height="30%" x="3" y="32" fill="none" stroke="black" stroke-width=".5"></rect>
                                                    <text x="5" y="44" font-size="10">SZ</text>
                                                    <title>Slow Zone</title>
                                                </svg>
                                            }
                                            @if (location.VRCDeviceID != "")
                                            {
                                                @foreach (var vrc in vrcs)
                                                {
                                                    @if (location.VRCDeviceID == vrc.DeviceID)
                                                    {
                                                        @*<ContextMenuTrigger WrapperTag="g" MenuId="vrcMenu">*@
                                                            <svg id="@vrc.DeviceID">
                                                                <rect height="100%" width="100%" fill="@gridBrush" stroke="black" stroke-width=".5" onclick="" class="location"></rect>
                                                                <rect x="@labelXPosition" y="2" height="30%" width="75%" stroke-width=".5" fill-opacity="1" stroke="black" fill="white"></rect>
                                                                <text x="11" y="14" fill="black" font-size="14">@vrc.DeviceID.Substring(3, 1) : @vrc.CurrentLevel</text>
                                                                <title>@vrc.DeviceID&#13;Current Level: @vrc.CurrentLevel&#13;Destination: @vrc.DestinationLevel&#13;@vrc.RunMode</title>

                                                                @if (vrc.RunMode == "Offline")
                                                                {
                                                                    <svg>
                                                                        <rect width="36%" height="30%" x="3" y="32" fill="white" stroke="red" stroke-width=".5"></rect>
                                                                        <text x="5" y="44" font-size="13" fill="red">!O</text>
                                                                        <title>Offline</title>
                                                                    </svg>
                                                                }
                                                                else if (vrc.RunMode == "Stopped")
                                                                {
                                                                    <svg>
                                                                        <rect width="36%" height="30%" x="3" y="32" fill="white" stroke="red" stroke-width=".5"></rect>
                                                                        <text x="7" y="44" font-size="13" fill="red" font-weight="600">S</text>
                                                                        <title>Stopped</title>
                                                                    </svg>
                                                                }
                                                                else if (vrc.RunMode == "Manual")
                                                                {
                                                                    <svg>
                                                                        <rect width="36%" height="30%" x="3" y="32" fill="white" stroke="red" stroke-width=".5"></rect>
                                                                        <text x="6" y="44" font-size="13" fill="red" font-weight="600">M</text>
                                                                        <title>Manual</title>
                                                                    </svg>
                                                                }
                                                            </svg>
                                                        @*</ContextMenuTrigger>*@
                                                    }

                                                }
                                            }
                                        </svg>
                                    </g>
                                @*</ContextMenuTrigger>*@
                            }
Someone is typing...

Post a Reply

You must be logged in to add a new post.
Number of online users: 1
An error has occurred. This application may no longer respond until reloaded. Reload 🗙