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); } } }
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); }
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; }
Hi Remy,
Remy Moerland said:The calling function in my main view model,
Why you do not test StatusInt, returned by LoadRootModelById? It is why the status exists.
Remy Moerland said: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.
Remy Moerland said: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.
Remy Moerland said: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
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Hi Jan,Thanks, I have added the StatusInt check.
Jan Šlegr said: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.
Jan Šlegr said: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?
Remy Moerland said: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.
Remy Moerland said: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 :-).
Remy Moerland said: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.