[CE 10.17.02.61 C#] Element preview for cell

Hi,

I am trying to get a preview of the cells in a cell library, 

I am using the following code to (try and) accomplish this:

The calling function in my main view model, which searches for the requested cell by name and finds it (correctly)

private void ShowSectionPreview(string selectedSection)
{
    string sectionName = $"Bvl_{selectedSection}";
    CellLibraryInfo selectedCell = CellsManager.Instance.BevelCells.FirstOrDefault(c => c.Name.Equals($"{sectionName}"));
    if (selectedCell != null)
    {
        DgnFile cellFile = selectedCell.File;
        ModelId cellModelId = cellFile.FindModelIdByName(sectionName);
        DgnModel cellModel = selectedCell.File.LoadRootModelById(out StatusInt status, cellModelId);
        //DgnModel cellModel = cellFile.FindLoadedModelById(cellModelId); 
        if (cellModel != null)
        {
            var graphicElementsData = cellModel.GetGraphicElements();
            var cellEle = graphicElementsData.ElementAt(0);
            //Here we add the PreviewUserControl as the child node of the WindowsFormsHost in the xaml
            MainWindow.Instance.PreviewsFormHostAA.Child = new ElementPreviewUserControl(cellEle);
        }
    }

}

Which in turn passes it on to the Element preview controller, which receives the cell correctly, but instead of drawing the cell only draws a white circle (which is not an element present in the cell itself)

public ElementPreviewUserControl(Element ele)
{
    InitializeComponent();
    Instance = this;

    DisplayableElement displayableEle = (DisplayableElement)ele;
    PreviewManager = new ElementPreviewManager(ref displayableEle, Bentley.DgnPlatformNET.MSRenderMode.Wireframe);
    PreviewManager.Dock = DockStyle.Fill;
    PreviewManager.Width = 95;
    PreviewManager.Height = 95;

    ElementPreviewPanel.Controls.Add(PreviewManager);
}

public void DrawPreviewElement(Element ele)
{
    DisplayableElement displayableEle = (DisplayableElement)ele;
    if(displayableEle == null)
    {
        MessageCenter.Instance.ShowErrorMessage("Element to preview is invalid", null, true);
        return;
    }

    Panel panel1 = new Panel();
    panel1.Size = new Size(50, 50);
    panel1.Location = this.Location;
    panel1.BackColor = Color.Cyan;
    panel1.BringToFront();
    ElementPreviewPanel.Controls.Add(panel1);
}


And finally the OnPaint method where the magic happens
public ElementPreviewManager(ref DisplayableElement ele, MSRenderMode renderMode)
{
    DisplayableEle = ele;
    RenderMode = renderMode;
}

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    ViewFlags viewFlags = ViewInformation.GetDefaultFlags();
    viewFlags.Camera = false;
    viewFlags.RenderMode = (int)RenderMode;
    viewFlags.Grid = false;
    viewFlags.FastCell = true;

    DisplayableEle.CalcElementRange(out DRange3d eleRange);
    DPoint3d origin = eleRange.Low;

    DPoint3d range = DPoint3d.Subtract(eleRange.High, eleRange.Low);
    Rectangle rect = new Rectangle(Location, new Size(95, 95));
    DisplayElemHandle(BytesToIntptr(DisplayableEle.ElementHandle), viewFlags, rect, null, origin, range);
    
}

public static IntPtr BytesToIntptr(byte[] bytes)
{
    int size = bytes.Length;
    IntPtr buffer = Marshal.AllocHGlobal(size);
    Marshal.Copy(bytes, 0, buffer, size);
    return buffer;
}


However the result isn't what I expected:


While the cell itself looks like this:


What am I missing/doing wrong here in order to be able to draw the cell?

Alternatively I've tried drawing the loose elements, but then I only get the first element in the cell file, and am not sure how I can numerate over and add all elements to the preview handler (which would also be a suitable option for me)

Regards,
Remy

  • Hi Remy,

    The calling function in my main view model,

    Why you do not test StatusInt, returned by LoadRootModelById? It is why the status exists.

    which receives the cell correctly

    It does not! (I think)

    What you do is that you find the model (representing the whole cell), receiving graphic elements collection and get the first element, not the whole cell.

    to the Element preview controller

    Where this controller comes from? Is it standard MicroStation API object, or something you developed?

    I remember PreviewControl class exists somewhere in MicroStation dll file, but I do not recall anything like ElementPreviewManager.

    and am not sure how I can numerate over and add all elements to the preview handler

    I am not familiar with the handler you use, but I guess you can iterate all elements in model (cell) and to create new (ad-hoc) cell and display it.

    The PreviewControl I mentioned above uses ElementAgenda, which is similar concept: Add all elements (the model content) to the agenda and display it.

    Regards,

      Jan

  • Hi Jan,

    Thanks, I have added the StatusInt check.


    What you do is that you find the model (representing the whole cell), receiving graphic elements collection and get the first element, not the whole cell.

    Maybe I misunderstand what it is exactly I am retrieving here, but the element I am trying to place I have placed into a group (tried with both a normal group and graphical group), when I then inspect which elements are returned by "GetGraphicElements()" I can see a single "CellHeaderElement" rather than each element individually. I had expected that this would represent the entire graphical representation of the element (group). Which might be a wrong assumption.




    Where this controller comes from? Is it standard MicroStation API object, or something you developed?

    I remember PreviewControl class exists somewhere in MicroStation dll file, but I do not recall anything like ElementPreviewManager.

    ElementPreviewController is indeed my own class.
    I tried looking up the PreviewController class in the documentation (using the SDKHelp from Robert) but am unable to find anything (in the .NET api or other). Is this a separate DLL?


  • when I then inspect which elements are returned by "GetGraphicElements()" I can see a single "CellHeaderElement" rather than each element individually.

    If I understand your code right, you open a cell library, load this file and access found model, that represents the placed cell. The model itself is cell, and everything what is in the model is the cell content.

    I do not know what structure the placed cell has, but it looks like for me that there is a cell inside cell.

    I tried looking up the PreviewController class in the documentation (using the SDKHelp from Robert) but am unable to find anything (in the .NET api or other).

    It's not a surprise ;-)

    But this class was discussed several times already (and it's why I found it :-).

    Is this a separate DLL?

    Useful classes are spread over many assemblies, even "public / documented" API is in several dll files. To find other (e.g. WPF and WinForms related) requires to search dll files content.

    PreviewControl class is located in DgnDisplayUI2.dll.

    Regards,

      Jan