enable visualization in listbox windows phone 8 - c#

am trying to show high quality images in phone ,as my image's size is too large app shows memory warning exception. so i tried visualization .but every time the listbox loads it loads whole data
xaml code:
<ListBox x:Name="ImageStack"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
VirtualizingStackPanel.VirtualizationMode="Recycling"
>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"></VirtualizingStackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Resources>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Image Source="{Binding bimage}" />
<TextBlock Text="{Binding impath}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and i used an IList
ImageStack.ItemsSource = new VirtualSongList();
and inside virtualsonglist class
object IList.this[int index]
{
get
{
// here is where the magic happens, create/load your data on the fly.
// Debug.WriteLine("Requsted item " + index.ToString());
System.Diagnostics.Debug.WriteLine(index.ToString());
return new im { impath = "yyyyyyyyy", bimage = new BitmapImage(new Uri(#"Assets/c"+index+".png", UriKind.Relative)) };
}
set
{
throw new NotImplementedException();
}
}
can anyone suggest a efficient way to display high quality image galley in windows

Use LongListSelector that was built with Virtualization in mind.
Even in that case it might not solve your problem if you are being too aggressive with your image memory.
Since you have limited space in your WP screen try making and showing a thumbnail of your image instead at first using BitmapImage::DecodePixelHeight and BitmapImage::DecodePixelWidth instead of decoding the full thing and therefore storing the full thing in memory. You can still show the full size image inside a details page, one at a time, when the user selects to do so.
Also try experimenting with BitmapImage::CacheOption (or other caching techniques) to see how you can better keep your memory in check.

Related

Reordering ListBox elements with gong-wpf-dragdrop causes visual bugs

Task
My task was to be able to change the order of the service cards in the ListBox by dragging and dropping. I found a good solution on StackOverflow that has a lot of useful features (gong-wpf-drag drop, https://stackoverflow.com/a/33367826/19631476).
Problem
However, I had to face an unpleasant visual bug: when I drag the service card, there is some label that indicates where the dragged object will be moved. So, for some reason, this label is clipped if a number of objects are also clipped and not visible in the ListBox. However, when scrolling, the cropping does not disappear. Moreover, then the label will always point to the line above, wherever it is.
Problem demo
below I will present some screenshots demonstrating the problem
the normal state of the separator
the separator is cut off due to the fact that the card does not fit into the container
the separator continues to be cut off after scrolling
the separator is shifted up a line, and is still clipped, despite the fact that I move the elements already in another line
My code
This is how my ListBox element looks like:
<ListBox
Margin="10 0 10 10"
Background="Cornsilk"
MinWidth="300"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.SelectDroppedItems="True"
ItemsSource="{Binding ServicesListCollectionView.View}"
SelectedIndex="{Binding SelectedServiceIndex}"
SelectedItem="{Binding SelectedService}"
d:ItemsSource="{d:SampleData ItemCount=5}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border AllowDrop="True" Style="{StaticResource BorderStyle}">
<DockPanel Background="GhostWhite">
<!-- Service Card Template-->
</DockPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
it contains a custom container so that the service cards can be arranged as a grid from top to bottom
What have I tried to do?
The idea came to my mind to prohibit the use of ScrollBar for the ListBox element. It worked, and the visual bug sort of disappeared. But you can't leave it like that. I wrapped the ListBox in ScrollViewer and allowed it to scroll vertically. This visual bug is no longer there:
code:
<ScrollViewer VerticalScrollBarVisibility="Auto" x:Name="ServiceScroll">
<!-- Here is ListBox -->
</ScrollViewer>
However, this solution is not suitable:
I lose control of scrolling in the ListBox and can only use scrolling on the ScrollViewer itself
Scrolling also becomes unavailable when dragging items.
the second problem can be solved by specifying the dd:DragDrop.DropTargetScrollViewer ScrollViewer with binding to the ScrollViewer element:
<ScrollViewer VerticalScrollBarVisibility="Auto" x:Name="ServiceScroll">
<ListBox
...
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.SelectDroppedItems="True"
dd:DragDrop.DropTargetScrollViewer="{Binding ElementName=ServiceScroll}"
...
></ListBox>
</ScrollViewer>
but in this case, the visual bug described above appears again, and also, this solution still does not allow you to scroll through the elements inside the ListBox using the mouse wheel.
Any ideas?
To be honest, I do not know what to do. Has anyone encountered anything described above?
Maybe I'm doing something wrong, which is why I get such strange behavior? What's wrong with scrolling?
Maybe you have good solutions to solve the problem? How else would it be possible to solve the issue of dragging items to the ListBox in the most flexible way?

Out of memory Exception on Listview with images and inkcanvas UWP

my idea is to create a listview with images, over each image I would like to insert a InkCanvas.
I tried two ways and both have problems.
First way.
I created the listview with its DataTemplate:
<DataTemplate x:Name="ListViewItemTemplate">
<Grid>
<Image></Image>
<InkCanvas></InkCanvas>
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Name="ListItemsPanelTemplate">
<VirtualizingStackPanel Orientation="Vertical">
<VirtualizingStackPanel.ChildrenTransitions>
<TransitionCollection/>
</VirtualizingStackPanel.ChildrenTransitions>
</VirtualizingStackPanel>
</ItemsPanelTemplate>
<ListView x:Name="list"
ItemTemplate="{StaticResource ListViewItemTemplate}"
ItemsPanel="{StaticResource ListItemsPanelTemplate}">
</ListView>
c#:
List<Image> pages = new List<Image>();
list.ItemsSource = pages;
In this way, the listview uses virtualization, when I write in a inkview, the stroke is copied every 5 inkview. It's not good.
If I remove the virtualization:
<ItemsPanelTemplate x:Name="ListItemsPanelTemplate">
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
It occurs the problem of the second way. Written below.
Second way:
I created a usercontrol PageFormat for the DataTemplate like this:
<UserControl>
<Grid Background="White">
<Image x:Name="image"></Image>
<InkCanvas x:Name="ink" ></InkCanvas>
</Grid>
</UserControl>
<ListView x:Name="list" ></ListView>
c#:
List<PageFormat> pages= new List<PageFormat>();
list.ItemsSource = pages;
In this way I have the following problem:like in this question
When I create more than 125 InkCanvas I have a memory problem.
I prefer the second way because I can play with the formatting of the page directly in a usercontrol, but I can not solve these problems.
I would like to solve the problem of generating InkCanvas the System.OutOfMemoryException error.
How can I solve it?
Thanks so much.
If you are 100% sure that InkCanvas is the cause of out of memory exceptions, you could do the following pseudo-system:
when a user is not editing an item, it should be persisted to disk/memory and a bitmap rendered and presented out of it.
when a user starts editing an item, de-serialize its data and realize it as an InkCanvas
i.e. use less resource-intensive types wherever it is appropriate
EDIT
Here's the solution to the fact that rendering an InkCanvas to a RenderTargetBitmap will produce a blank image:
https://mtaulty.com/2016/02/16/windows-10-uwp-inkcanvas-and-rendertargetbitmap/
(requires Win2D package)

Improve performance in WPF with many UIElements

I'm very new in WPF and I need some advise on how to create a view with many UIElements at the same time. What i want to do, is to view some kind of table with fixed width and height for each cell. In each cell could be a random number of textblocks with a different back and forecolor (see image).
Image for table-like view with many UiElements
That is what I have done so far... I created an usercontrol for the content of one cell which binds the items in an itemcontrol.
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Backcolor, Converter={StaticResource IntegerToBrushConverter}}" >
<Viewbox MaxHeight="20" >
<TextBlock TextWrapping="Wrap" Text="{Binding Caption}"
Foreground="{Binding Forecolor, Converter={StaticResource IntegerToBrushConverter}}"/>
</Viewbox>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This usercontrol is also binded to an itemcontrol for representing the x-axis of my table.
<ItemsControl ItemsSource="{Binding}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:DayView DataContext="{Binding Days}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And the same is done for the y-axis with an nice scrollviewer around. So, the problem is, that there are many many elements in the virtual tree. In my sample case there are over 60.000 elements listed in the tree. This results in a bad performance, when opening the view. The scrolling performance is quite okay, but he takes several seconds to open the view.
I've tried some things like the CacheMode and so on, but all of that doesnt effect the opening performance. Using a VirtualizingStackPanel results in bad scrolling performance. I even cant figure out what takes so long to build up the Ui. Seems that he need a lot of time to measure all UiElemtents, but Im not sure...
Are there tips to make such an UiElement rich view any faster? As I said, Im very new in WPF and that is only a performance test. We have such an Ui in Winforms, but there, the whole table was user painted. In WPF it is so easy to rebuild the Winforms design with stock content-controls that I only want to draw all for myself as a last resort.
Take a look here for a possible solution to your problem by using virtualization:
WPF Data Virtualization
Also if you want to go another way, there are commercial 3rd party WPF control libraries that handle virtualization with various degrees of success. To name a few: Xceed, Syncfusion, DevExpress and Telerik.
I even cant figure out what takes so long to build up the Ui.
Hoping you are using VS2015 (or something better), there are a few ways to get an answer to what is taking so long. Visual Studio has a live visual tree tool (Debug->Windows) where you can see the visual tree in real time and it might help you find and eliminate some of the UI elements you don't really need (like borders inside more borders, etc)
Second, you can run the Diagnostic tools (Alt+F2), choose CPU usage and that should generate a report where you can see where your program is spending the most time. Hopefully this will isolate the issue to certain methods that can be optimized afterwards.
Also, more detail about your problem would be welcome. What is the code that populates the ItemsSource do exactly?

GridView out of memory with large number of ObservableCollection

I'm developing a Universal Win App and the issue is present on both platforms. I've a ObservableCollection with products, object properties are bound from xaml DataTemplate and ObservableCollection is set as ItemsSource to GridView.
private ObservableCollection<Product> productList = new ObservableCollection<Product>();
Bound products have images too.
<Image
CacheMode="BitmapCache"
Source="{Binding ImageUrl}"
Stretch="Uniform" />
GridView
<ScrollViewer
x:Name="ProductList_GridView_ParentScrollViewer"
VerticalScrollBarVisibility="Hidden"
Grid.Row="1">
<StackPanel
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch">
<Viewbox
AllowDrop="False"
ScrollViewer.HorizontalScrollMode="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollMode="Disabled"
Stretch="UniformToFill">
<GridView
x:Name="ProductList_GridView"
Margin="15,9.5,15,0" />
</Viewbox>
</StackPanel>
</ScrollViewer>
Also I've a kind of pagination setting which make request each time scrollable height is equal to vertical offset. And I'm adding new items to ObservableCollection by doing
foreach (var item in requestResult.products)
{
productList.Add(item);
}
this seems to work fine until i reach certain number of items. After that the app just crashes. My app's memory consumption reaches as high as 800Mb's before crashing on 2GB ram device. On 512Mb ram it crashes a lot earlier.
How can I fix the issue? Do I need to change the way I did this pagination. Or can it be fixed with small changes. I guess the problem is with Image but not sure. Isn't CacheMode="BitmapCache" supposed to fix the memory problem?
Your GridView virtualization is broken because you are wrapping it in a ScrollViewer and all items are rendered at once (and using much more memory).
If you only leave the following XAML you will have no more memory problems:
<GridView
x:Name="ProductList_GridView"
Margin="15,9.5,15,0" />

Calendar Programming: How can I place, create and size items that represent a task using MVVM?

I just have a conceptual question here. First of all I am programming a Windows 8.1 App using C# and XAML as well as the MVVM-Light Toolkit.
I am working on a Schedule at the moment which is backed by a calendar. The calendar should have a "DayView" which consists of a timeline on the left that goes from top to bottom. Now on the right of that timeline I want to show something similar to a rectangle as a visualization for a given task with a height that represents its duration. Every task has a starting time so the top of that rectangle should be placed next to the corresponding entry in the timeline.
Well I hope it is clear what I am trying to say here basically that should look similar to the Calendar-App coming with Windows 8. I will post a screenshot of that below that post.
Now I have tried or thought of multiple things by now that lead to more or less complicated problems. The best approach I had was creating a List a placing it on the right of that timeline. Now that List would contain a huge amount of items (maybe one for each pixel) which will be changed in size. The size then is 0 or in relation to the duration of the task depending on whether there is a one or not.
But that leads to huge problems when it comes to changing an entry or having more than one task for the same time since those items wont overlap. And I don't want to place more than one or two of those per page since the performance-issue would be overkill...
One of the issues I have is that I am using the MVVM-Concept and don't know how to be able to create new UI-Elements such as a rectangle without touching the code-behind. That is why basically the only thing I have thought about by now were lists...
I hope it is clear what I meant.
Thank you very much for your help!
FunkyPeanut
Problem solved using a Grid as the ItemsPanel of an ItemsControl:
<ItemsControl Grid.Column="2" ItemsSource="{Binding Day.ItemsList, Source={StaticResource Locator}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid Width="20"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Height="{Binding Height}" Width="20" Margin="{Binding Margin}">
<Grid.Background>
<SolidColorBrush Opacity="{Binding Opacity}" Color="{Binding ColorHash, Converter={StaticResource HexToColorConverter}}"/>
</Grid.Background>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
With the following Data:
ItemsList = new ObservableCollection<object>(tmpPeriodsList.Select((x, i) => new
{
ColorHash = x.ColorHash,
Index = i,
Margin = StartPosition(i),
Opacity = 0.6,
Height = 45,
}));

Categories

Resources