What is/are the main disadvantage of VirtualizingStackPanel? If it doesn't have any, then why it is not made as a default panel behavior/template in ItemsControl?
The MSDN page on the VirtualizingStackPanel Class has the following statements:
The word "virtualize" refers to a technique by which a subset of user interface (UI) elements are generated from a larger number of data items based on which items are visible on-screen.
and
Virtualization in a StackPanel only occurs when the items control contained in the panel creates its own item containers.
and
VirtualizingStackPanel is the default items host for the ListBox element.
From this it looks like for the "normal" use of a StackPanel as a host for buttons, text blocks etc. virtualisation wouldn't offer any advantages or might even impose a performance overhead. When used in a ListBox virtualisation does have benefits as a) item containers are created by the items control and b) there are likely to be more elements in the list than can be shown on the screen at any one time.
Related
Assume that I need to create a class called PictureWall, which will be used to show pictures.
Now I find that Panel and ItemsControl can both be used to hold Children elements. So should the class PictureWall derive from Panel? or should it derive from ItemsControl.
Note: This is not a real requirement, it's just a hypothetical question. The real question is: when should I create a subclass of Control (or ItemsControl) and when should I create a subclass of Panel?
Note 2: This imagined picture wall control is not to be used in one application only. It may be used by other developers. If it derives from Panel or ItemsControl, it'll expose the property named Children to other developers. So in this case, deriving from Control is a better idea, right?
Note 3: This imagined picture wall control has its own default way of loading certain pictures (for example, pulling pictures from a server) and it does not want this way to be messed around. If this is the case, then we should not inherit ItemsControl, right?
Panel is a container that is used to arrange its children. For example: Grid with a title and one button on the bottom and an image on center - Grid is very flexible to help you move stuff and arrange them when you change the size of window etc.
ItemsControl is a control that helps you with a collection of items. Let's take a concrete example: Listbox. You can very easly show a list of items, applay template to all of them, so on and so forth.
Control class is basically a UI element that can have its own template.
Note that, it is a way much better to define own UserControl, edit template or style of your PictureWall, insted of subclassing (there are many advantages, for example you can use Blend to redefine the style).
Edit:
# note2
If I were you I would make my own User Control to reuse existing controls to make what I want. If that won't be enough I would subclass Control.
[StyleTypedProperty(Property = "FooStyle", StyleTargetType = typeof(Control))]
public partial class MyDangControl: Control
{
...
# note3
This is a bad idea to combine all in one. You should split the logic that fetch the data form yout Picture Wall. For instance, user presses thumbnail to download the image and whole UI hangs. Horrible UX.
To be crystal clear, let me quote Pro WPF in C# 2010
Control
This is the most common starting
point when building a control
from scratch. It’s the base class for
all user-interactive widgets. The
Control class adds properties for
setting the background and foreground,
as well as the font and alignment of
content. The control class also places
itself into the tab order (through the
IsTabStop property) and introduces the
notion of double-clicking (through the
MouseDoubleClick and
PreviewMouseDoubleClick events). But
most important, the Control class
defines the Template property that
allows its appearance to be swapped
out with a customized element tree for
endless flexibility.
ContentControl
This is the base class for controls
that can display a single piece of
arbitrary content. That content can be
an element or a custom object that’s
used in conjunction with a template.
(The content is set through the
Content property, and an optional
template can be provided in the
ContentTemplate property.) Many
controls wrap a specific, limited type
of content (like a string of text in a
text box). Because these controls
don’t support all elements, they
shouldn’t be defined as content
controls.
ItemsControl
ItemsControl is the base class for
controls that wrap a list of items but
don’t support selection, while
Selector is the more specialized base
class for controls that do support
selection. These classes aren’t often
used to create custom controls,
because the data templating features
of the ListBox, ListView, and TreeView
provide a great deal of flexibility.
Panel
This is the base class for controls
with layout logic. A layout control
can hold multiple children and
arranges them according to specific
layout semantics. Often, panels
include attached properties that can
be set on the children to configure
how the children are arranged.
They both can be used to display elements, but really an ItemsControl offers much more functionality. In addition, an ItemsControl doesn't really display it's elements, it leverages a Panel to do that.
An ItemsControl can display a list of items, which may or may not be UIElements/Visuals. The items can be templated using a configurable DataTemplate, which ultimately determines how the item is displayed. In addition, then items can be bound to an observable collection so it will automatically update.
Neither of these features are supported by a Panel. DataTemplates can be used, but you have to manually create an associated ContentControl/ContentPresenter and add it to your panel.
Ultimately, their functions are different. A Panel is used to display UIElements/Visuals. An ItemsControl is used to display any type of data and apply templates as needed.
I'm building a WPF application to visualize a load of items (a few thousand). For this i'm using an ItemsControl of which the ItemsSource is set to a BindingList.
I've noticed that it takes some time to initialize the screen... The main bottleneck is the creation of TextBlock elements (the data template of the items contains 4 TextBlock elements). Once the screen is initialized (when all WPF elements are created), rendering is quite OK.
I've implemented zooming and panning, so i was thinking about making the appearance of the items dependent on the zoom level and the center point (a bit like Google Maps: data is only visualized for regions that are into the view).
How can this be done? Is there any way in WPF to ask the item or item container if it is currently clipped?
You can make your list virtualized. This way only the items that are visible will have UI controls created for them.
Check the ListView documentation, or this link may help:
http://www.codeproject.com/KB/WPF/WpfDataVirtualization.aspx
Jogy
I have a number of items which I wish to be contained in either a ListBox or an ItemsControl. The size of the control is fixed, but the size of its contents are not. It is possible for this control to have 13 items inside, but if the user wishes, only one is displayed at a time, and takes up the entirety of the available space. Two items visible roughly splits the available space in two and so-on.
I don't "require" selection, but I do require a context menu.
If I use a ListBox, I get almost everything I want EXCEPT that if I select an item on the far right, it will be centered and the view "jumps". I don't want this. However, if I use an itemscontrol, when the size of the items contained changes ItemsControl just draws completely wrong proportions (sets width to aprox 120% of what it should be if just one item were displayed).
Which control should I use? And I do I 'fix' it to do what I want?
What is the difference between a stackpanel and a virtualizingstackpanel in WPF?
A VirtualizingStackPanel can offer performance benefits when working with very large collections. It does so by only rendering and processing a subset of the data which is visible to the user vs. processing the entire list of data. By creating only UI elements for the visible items, this can greatly reduce the amount of work it has to do.
This is really only handy though if
You are data binding non-UI elements or elements for which UI must be created in the particular panel
You are data binding a lot of data
A StackPanel on the other hand, will up front create the controls for all elements contained within the StackPanel.
The VirtualizingStackPanel MSDN page has a decent discussion: http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.aspx
This is to do with the visual tree. The virtualizingstackpanel works with things like list boxes etc to reduce the size of the visual tree by only displaying visible items - this is useful where databinding is taking place.
I need to show a list of many text strings, each on a line.
I need items to be selectable, so i cant use an ItemsControl.
I only need one "column" and no sorting, so a DataGrid might be too heavyweight (???)
I need up to 1000 items, so a Listbox might be too lightweight (???)
What Silverlight control (or Toolkit control) would be best for this use?
The functional equivalent of is indeed .
If you need an ItemsControl that has Selection, use one of the classes the inherit from Selector (which coincidently itself inherits from ItemsControl):
1. ComboBox
2. ListBox
3. TreeView (Selector API)
4. AutoCompleteBox (Selector API)
All of these support the same ItemsControl API of ItemsControl.ItemTemplate=DataTemplate.
DataGrid has good performance because of virtualization:
The DataGrid boasts excellent performance with large sets of data
because it uses virtualization, unlike any other Silverlight control. That means the
DataGrid only retains in-memory objects for the data that’s currently visible, not the
entire set of data that’s loaded. This reduces the memory overhead dramatically and
allows it to practically hold thousands (or even millions) of rows. The only tradeoff is
that the DataGrid is slightly slower when scrolling, because it needs to clear the current
set of DataGridRow objects and load the information that corresponds to the new rows.
I would add the HeaderedItemsControl from the Silverlight Toolkit. Here's an article: HEADEREDCONTENTCONTROL & HEADEREDITEMSCONTROL