I am developing a reporting WinForm with Infragistics 12.1. I have 8 UltraGrids laid out in an UltraGridBagLayoutPanel so that they all appear in a single row. I don't want the user to be able to scroll within the individual grids but to have just one set of scroll bars for the panel. I've successfully done this part but to make the user experience acceptable I need to size the UltraGrids to suit. I am currently trying to code for the change of column sizes to resize the grids and change the location of any of the other grids to the right of the one changed. I currently have the following code:
private void marketUltraGrid_AfterColPosChanged(object sender, AfterColPosChangedEventArgs e) { switch (e.PosChanged) { case PosChanged.Sized: int totalColumnHeadersWidth = 0; foreach (Infragistics.Win.UltraWinGrid.ColumnHeader colHeader in e.ColumnHeaders) { totalColumnHeadersWidth += colHeader.Column.Width; } totalColumnHeadersWidth += 1; //add on an extra pixel just makes it look a little cleaner marketUltraGrid.MaximumSize = new Size(totalColumnHeadersWidth, marketUltraGrid.Height); exchangeRateUltraGrid.Location = new Point(marketUltraGrid.Margin.Left + marketUltraGrid.Width + marketUltraGrid.Margin.Right, exchangeRateUltraGrid.Location.Y); break; } }
The resize of the marketUltraGrid works using MaxiumnSize but assigning a new object to Location doesn't change its position within the client. I have to assign a new object rather than change the properties .Width and .Height because of this http://stackoverflow.com/questions/12681839/why-can-i-set-these-properties-in-the-ide-but-not-in-code. The values that create the new Point differ from the original location, but the resultant Location after the assignment is exactly the same as it was before. I think it is probably something to do with that they are children of the BagPanel, but I can't find the right property or method of the BagPanel to make it work yet.
Once I've got this section working I need to apply a similar approach to all of the remaining grids to the right of exchangeRateUltraGrid and create AfterColPosChanged events for all the other grids. I also want to resize the grids to fit the data which is loaded in the
private void GKPI1Report_Load(object sender, EventArgs e) event but haven't got that far yet.
Matthew,
The UltraGridBagLayoutPanel controls the position of the controls that it contains so setting the Location of grid controls inside it will have no effect. You might try setting the Width of the grid and then reset the Width of the UltraGridBagLayoutPanel to accomodate the new width. Let me know if that helps.
Hi Michael, thanks for this, it certainly sent me in the right direction. It's been very very difficult and quite frustrating, but I almost have the layout perfect now, certainly acceptable for now. In the end I learnt that I could override the LayoutEngine for the UltraGridBagLayoutPanel because it is derived from Panel, so that is exactly what I have done in a custom derived class. I also got that idea from this source http://msdn.microsoft.com/en-us/library/ms171727.aspx so in combination with your guidance I've achieved the desired result.
I wanted to share what I've achieved because seemingly questions have been asked and no one I've found has been able to provide an answer, so I had to do it the hard way. The biggest disadvantage to this approach is I had to completely ditch my design layout and start again based upon my custom control instead of the Infragistics class I started with.
Also in my approach I have used an UltraPanel to control the scrolling of the UltraGridBagLayoutPanel, which explains the parentpanel variable.
I've also subsequently learnt from sharing at our sprint review meeting with my fellow team developers that I could set the Max and Min sizes at design time to an appropriate size and then I would be able to use .Size to define the size of the UltraGrid. Although my approach is working I agree with them that this is a more elegant solution, which I will be implementing in the next sprint.
public class GKPIUltraGridBagLayoutPanel : UltraGridBagLayoutPanel { public GKPIUltraGridBagLayoutPanel() { } public override System.Windows.Forms.Layout.LayoutEngine LayoutEngine { get { return new GKPI1ReportUltraGridBagPanelLayoutEngine(); } } } public class GKPI1ReportUltraGridBagPanelLayoutEngine : System.Windows.Forms.Layout.LayoutEngine { public override bool Layout(object container, LayoutEventArgs layoutEventArgs) { Control affectedControl = layoutEventArgs.AffectedControl; UltraGridBagLayoutPanel panel; if (!(affectedControl is UltraGridBagLayoutPanel)) return false; else panel = container as UltraGridBagLayoutPanel; switch (layoutEventArgs.AffectedProperty) { case "Bounds": int widthOfAllControls = 0; foreach (Control ultraGrid in panel.Controls) { if (ultraGrid is UltraGrid) widthOfAllControls += ultraGrid.Margin.Left + panel.GetGridBagConstraint(ultraGrid).Insets.Left + ultraGrid.Width + panel.GetGridBagConstraint(ultraGrid).Insets.Right + ultraGrid.Margin.Right; } panel.MaximumSize = new Size(widthOfAllControls, panel.Size.Height); panel.MinimumSize = panel.MaximumSize; if (panel.Parent is UltraPanelClientArea) { UltraPanelClientArea parentpanelclientarea = panel.Parent as UltraPanelClientArea; if (parentpanelclientarea.Parent is UltraPanel) { UltraPanel parentpanel = parentpanelclientarea.Parent as UltraPanel; parentpanel.AutoScrollMinSize = panel.MaximumSize; } } break; case "Visible": break; case "AutoSize": foreach (Control c in panel.Controls) { if (!c.Visible) continue; if (c is UltraGrid) { UltraGrid u = c as UltraGrid; int largestbandColumnWidths = 0; int bandColumnWidths = 0; foreach (UltraGridBand ugb in u.DisplayLayout.Bands) { if (ugb.Hidden) { bandColumnWidths = 0; continue; } foreach (UltraGridColumn ugc in ugb.Columns) { if (!ugc.Hidden) bandColumnWidths += ugc.Width; } if (bandColumnWidths >= largestbandColumnWidths) largestbandColumnWidths = bandColumnWidths; bandColumnWidths = 0; } if (largestbandColumnWidths > 0) { u.MaximumSize = new Size(largestbandColumnWidths, u.Size.Height); u.MinimumSize = u.MaximumSize; } } } // have to loop for a second time because all the UltraGrids need to be sized before the UltraLables can be sized to match their widths. foreach (Control c in panel.Controls) { if (c is UltraLabel) { foreach (Control t in panel.Controls) { if (t is UltraGrid) { if (t.Bounds.Left == c.Bounds.Left) { c.MaximumSize = new Size(t.MaximumSize.Width, c.Height); } } } } } break; default: break; } return false; } }
Oh forgot to mention, I've only got one Band in my grids and I'm not likely to have one on this report. So largestbandColumnWidths = bandColumnWidths; section is completely untested for multiple Bands. I just realised at the time this was the correct approach to be taking to make it more generic.
Thank you for posting this. I think our Product Management team will find this very interesting and I am going to forward this to them. Let us know if you have further questions or if there is anything else we can help you with.