I'm looking for way to present equally sized elements in a fixed number of rows and any number of columns. (Think of iTunes' or Picasa's album view. I believe some platforms refer to this as a 'gridview')
A WrapPanel would do the job, but I'm binding against a very large collection of objects, so I need virtualization.
I've been looking around the web, and found both commercially available VirtualizationWrapPanels and blog posts on how to implement your own VirtualizationPanel, but I can't seem to find any simpler solutions.
Is it possible to arrange virtualized databound items in a grid-style view (fixed number of rows) with standard WPF components?
I've recently had to have a hunt round for similar functionality and struggled to find anything that was production ready.
I found a series of articles and sample code that contain a Virtualizing Tile Panel.
I've been using it and it has been fairly stable. There were some changes that needed to be made though. We had to add some of the keyboard control into the panel as it wasn't implemented, tabbing needed to be changed as well as adjusting tile sizes, etc. It's a good starting point if you decide to roll your own.
One major caveat though was that it also MUST have a parent that is constrained to a limited size else it errors out. This is not normally an issue as you will want it to be limited in size so you can enable scrolling. There may be a solution to this particular problem but we didn't have time to investigate.
A quick-and-dirty solution is to use a list (in your case a horizontal one) of "grouping items" (in your case vertical ones) which will determine desired number of rows. Virtualization will occur on the "groupers".
It is the responsibility of the Panel to provide Virtualization. Unfortunately the framework only provides a virtualizing StackPanel:
http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingpanel.aspx
There is a very good blog post that provides a virtualizing WrapPanel here:
https://blogs.claritycon.com/custom-panels-in-silverlight-wpf-part-4-virtualization-7f3bded02587
Another alternative is to use a DataGrid, this will virtualize for you.
Related
I am new to professional development of UI application. I wonder what the normal approach to decide the layout of the each UI element.
Do people hard-code the size elements according to the design time monitor size? And later scale the UI size dynamically?
Or do people use some dynamical approach to set each UI element proportional according to screen size? I meant if there's a method dynamically to set controls size proportional to screen size and that ratio is hard-coded by programmer. Obviously, Dockpanel or viewbox are automatic adjusting. Or do people usually decided size upon design time?
Or there're other common approach?
Its generally recommended to have size of the elements proportional according to screen size. WPF has lot many features to achieve these functions. Since you where new to WPF, have brief knowledge about the WPF Panels. Also if you would like to stick with the existing layout and you need to expand the layout proportionally make use of ViewBox in WPF.
There is no simple answer to this. The WPF composition does a lot of hard work for you, if you let it.
If I can help it, I do not specify Width's and Height's but I would be lying if I said that I never do. In some data entry applications, there is no choice but where I do have a choice, I will let the WPF composition system do the work for me. Margins are the only layout property that will always get a look-in.
The WPF Composition system
The WPF Composition system will pass over your logical tree twice, once to measure the elements and once to arrange the elements based on the collected information. Some elements, such as panels, will attempt to take up as much space as they can. Some elements will attempt to constrict their contents as much as possible. Some elements will take up only the space they need.
An example is if you put a TextBox in a Grid without specifying Width's and Height's, the TextBox will take up the entire 'content' area of the Grid. If you do the same with a TextBox and a StackPanel, the StackPanel will constrain the TextBox to the MinHeight of the TextBox. Put a CheckBox in the Grid and it will take up only the area it needs.
Conclusion
There is no simple way to learn this other than to play.
I recommend reading the following links
WPF Architecture
Trees in WPF
They are both long reads but worth while. They will give you the theory you need to search for more practical applications of WPF and there are a lot of good blog entries out there that cover this topic.
I am looking to display tabular data (tv channels), but with options such as DataGrid/UniformGrid/Table with FlowDocument/etc. I cannot figure out what would be the best option. The main issues is that the cells aren't uniform in size as it varies based on length of time, and I would like to put padding between them as well. Additionally, I need to only be able to display a portion of the table, and allow them to scroll Up/Down/Right to view the rest.
What would be the best WPF Control Option for this? Here is a small illustration of what I am going for. The white square in the upper left is what I would want to display at start, and allow them to scroll to the rest of it.
There are several ways to accomplish what you're trying to do here. If performance is not an issue then I would ignore virtualization and try the DockPanel The drawback here is that you would have to add the items in order rather than adding them by row.
Another option would be to use two stack panels (one in each direction). This addresses the adding issue, but requires the use of more panels.
Both of the previous two options would require individual items to have their height/width set.
A final option (depending on how large your grid is), would be to use a Grid with fixed sized rows and columns with items that span rows (using the rowspan property). The drawback of this method is that I don't know of any good way to create this control in xaml for unspecified numbers of rows/columns so you would have to create it in code to get the needed number of rows/columns.
If you have performance issues you could try using the VirtualizingStackPanel. If this still doesn't meet your performance requirements then you will need to subclass the VirtualizingPanel and tailor it to meet your specific needs.
See here for more information on Panel performance.
I suggest trying the two StackPanel method first, then the VirtualizingStackPanel method and finally, if that doesn't work, then try the VirtualizingPanel
Padding is easily accomplished by setting the Margin property on each subcontrol.
For scrolling use the ScrollViewer
I am new to WPF environment and I am experiencing some problems like if there are alots of things how do we manage them.for example I have three borders each of same size same location and they contains controls like textboxes etc etc we construct them sequentially but when it comes to edit we get in trouble modifying the border that is at bottom.
So in short how do we manage many controls on single page so that it remains easy to edit
Not sure I completely understand your concerns, but here are several point that make editing WPF UI pretty easy:
Correct usage of layout panels. If you will use approach with absolute positions for each control then it might become a nightmare to move or resize some of your controls. Correct layout (and panels such as DockPanel/StackPanel/etc) might help you a lot.
Incapsulating repeatable parts. WPF has a lot of feature to avoid repeating UI code. I'm talking mostly about Styles and Control templates at the moment. If you have your borders repeating through the entire window, maybe you should think on extracting this border as a ControlTemplate for ContentControl for example?
but I've found that encapsulating controls such as borders, textboxes etc in User Controls helps to keep things well managed (not to mention helps reduce code), similarly using a Resource Dictionary to store styles/animations is useful for very big projects (remember though that the local resources will take precedence when applied so remove them if they not in use)
furthermore, using Layout Panels such as Stacks,Grids and Dockpanels allows you to collapse User Controls when not needed or otherwise (also I've found that for some reason, Grids allow controls to overlap (when items are not correctly ordered in Grid Rows and Columns) which can lead to some elements not being seen in design.
Plan your layout properly and think through which Panels would be best for them, having to go back much later and change can be annoying (though admittedly it happens).
Also remember to use partial classes to properly structure your stuff, having to read through 1000+ lines of code to find something can be a nightmare.
Boy did I get an education looking into this. I guess I've been spoiled by Powerbuilder, which has fantastic functionality for this out of the box.
Does anyone seriously write custom documentpaginator objects to handle reporting needs for their LOB apps? I want to be able to print "for free" and not have to code like crazy just to take whats on the screen and throw it on paper.
How are people doing this? Does anyone have a recommended 3rd party for allowing printing of largish datagrids?
Thanks
Paginating datagrids is a huge, huge pain. Simply drawing the grid on a page will not work as you have to handle things like fixed layout, expanding cells horizontally and vertically to show all data, word wrapping, splitting columns and rows into the page margin, splitting cells that overflow a page into multiple pages. Remember you can't scroll or resize a control on a piece of paper. Even if you find a magic control that can do all that, a grid with borders, shadows, and backgrounds that look good on a screen won't look good on paper.
For an old WinForms app that printed datagrids we implemented a completely separate report API for printouts. We printed the underlying ADO.Net dataSource using the free ReportViewer control. A tutorial is at gotreportviewer.com.
I've found the easiest way is to implement a generalized DocumentPaginator class for paginating anything I can put on screen. With my DocumentPaginator I don't need to worry about printing because I can take any arbitrary WPF control and tell it to print, and it will take multiple pages if necessary to display all the data.
I also use an inherited attached bool property "PrintView" that the user can control. Some of my controls change their appearance somewhat using a trigger on the "PrintView" property, so they will look better when printed.
I describe my DocumentPaginator solution in more detail in this answer, including a description of the algorithm required.
How can I add column headers to a Silerlight ItemsControl? I need a fast way to display a List of items that contains also some header info.
This may seem like a simplistic question but why not use the DataGrid in readonly mode?
The downside with data grid is it doesn't use a virtualised ItemsControl so performance may suffer if you are trying to list hundreds of items with many columns.
There's nothing built into the ItemsControl itself, but there's nothing to stop you from making a custom control that has that kind of functionality. It's a little work up front for the ability to reuse it later if it's a piece of UI you need frequently.
Adding too much functionality to it might be overkill though; if you need column sorting or automatic column/header generation, you may find that a DataGrid (as Anthony pointed out already) would be a faster way of getting a lot of functionality for free.