This what i am trying to achieve with WPF. A textblock as title and below buttons in a wrappanel
.The problem is that this needs scrolling etc.
I have achieved this using ItemsControl and binding for each group.
I have an ItemsControl that has a stackpanel as paneltemplate and its itemtemplate is a textblock and a wrappanel .
It works but it is slow at instantiation at slow intel gma + atom machines when items are many . It seems that rendering isnt the problem but creation of the Visual Tree. So my only bet here is to create a custom panel with virtualization i guess?
Here is what i have done.
http://pastebin.com/u8C7ddP0
Above solution is slow at some machines.
I am looking for a solution that it would take max 100ms at slow machines to create. Thank you
UPDATE
public class PreferenceCheckedConvertor : IMultiValueConverter
{
public object Convert(object[] values, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
var preference = values[0] as OrderItemPreference;
var items = values[1] as ObservableCollection<OrderItemPreference>;
var found = items.FirstOrDefault(item => item.Preference.Id == preference.Preference.Id);
if (found == null)
{
return false;
}
return true;
}
public object[] ConvertBack(object value, Type[] targetTypes,
object parameter, System.Globalization.CultureInfo culture)
{
try
{
return null;
}
catch (Exception e)
{
return null;
}
}
}
ff
public class PreferenceConvertor : IMultiValueConverter
{
public object Convert(object[] values, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
var preferences=values[0] as IEnumerable<Preference>;
var items=values[1] as ObservableCollection<OrderItemPreference>;
var newList = new List<OrderItemPreference>(preferences.Count());
foreach (var preference in preferences)
{
var curItem = items.FirstOrDefault(item => item.Preference.Id == preference.Id);
if (curItem == null)
{
newList.Add(new OrderItemPreference()
{
Preference = preference
});
}
else
{
newList.Add(curItem);
}
}
return newList;
}
public object[] ConvertBack(object value, Type[] targetTypes,
object parameter, System.Globalization.CultureInfo culture)
{
try
{
return null;
}
catch (Exception e)
{
return null;
}
}}
To make WPF layout faster, you need to enable virtualization. In your code:
ScrollViewer
which wraps all your controls.Replace top-level
ItemsControl
withListBox
:Replace
StackPanel
in theListBox
'sItemsPanel
withVirtualizingStackPanel
:This will enable virtualization for top-level items. On my computer, this allows to display 100,000 items within 1 second.
N.B.:
While you think that the bottleneck is WPF layout, you may be wrong, as you haven't profiled your application. So while this answers your question, it may not actually solve the problem with the window working slow. Profilers can analyze not only your code, but framework code too. They analyze calls, memory etc., not your sources. They are a great tool to improve your performance and the only true way to find the source of performance issues.
For the love of all that is holy, please, read http://sscce.org! You won't have enough reputation to give to solve all your code issues if you don't try to make your examples short, self-contained and compilable. Just to run your example, I had to create my own view-models, get rid of all irrelevant code, simplify bindings, not to mention all kinds of your own converters, controls and bindings which are nowhere described.
UPDATED to support .NET 4.0
It is necessary to set
local:PixelBasedScrollingBehavior.IsEnabled="True"
both onListBox
andVirtualizingStackPanel
, otherwise scrolling will work in item mode. The code compiles in .NET 4.0. If .NET 4.5 is installed, it will use new properties.Working example:
MainWindow.xaml
MainWindow.xaml.cs