I am trying to make a long ListBox with each ListBoxItem being a tile with a small 100x100 logo inside it. Right now it's very slow - using more than 5-6 seconds just to become responsive. Since the images are downloaded from the web async (and each one is stored inside each own model instance), I don't know how to check when they have all downloaded either (i.e. no progress indicator to cover the delay).
Do you have any idea as to how I can do this in the most effective way possible?
XAML:
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate>
<ItemsPresenter />
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<ListBoxItem>
<Grid Name="ChannelTile" Tap="ChannelTile_Tap">
<Rectangle Fill="{StaticResource LightGrayColor}" />
<Image Style="{StaticResource Tiles_Image}" Source="{Binding Image}" />
</Grid>
</ListBoxItem>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If you reference the images in binding (Source={Binding Image}) by URL, try using the LowProfileImageLoader from PhonePerformance (http://nuget.org/packages/PhonePerformance)
Related
I have an app that creates a list of images. As it is its displayed in one single row, and I feel it could be more efficient putting them in two columns, I tried removing the Stackpanel:
<ListBox
ItemsSource="{Binding Images}"
SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding SmallLogoURL}" Height="75" Width="75" Margin="0,0,10,0" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But I still get it in a single column list :-/
You could just load it through a WrapPanel as your ItemsPanelTemplate like;
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
PS - You can set the Width on your WrapPanel to reflect the amount of columns you're shooting for since your images already have a fixed size to accomplish just two columns or just leave it to whatever it can fill by itself.
Hope this helps.
I have a listbox with the following structure. Data displays well and no issues there. I want to get some animation affect for the StackPanel, but since it is inside the DataTemplate, I am not able to use Blend to get my desired animation affect.
I guess I can write an event handler and code for that, but is that the best approach of achieving animation for ListBox items?
<ListBox Height="600" ItemsSource="{StaticResource learn}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Height="100" Orientation="Horizontal">
<TextBlock Width="0" Text="{Binding ID}" />
<Image Height="100" Width="100"/>
<StackPanel Orientation="Vertical" Width="319" VerticalAlignment="Center">
<TextBlock TextWrapping="Wrap" Text="{Binding Text}" Margin="6,0,0,0" FontSize="29.333" />
<TextBlock TextWrapping="Wrap" Text="{Binding Description}" Margin="6,0,0,0" FontSize="16"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Okay, all you need to do is to create a new user control and add all your animations to that user control and start animation where you want. In the list box data template, create an instance of that data template.
Steps to reproduce:
Create a new User Control in the project.
Give in the animations to the animations to that user control in blend.
Add the user control in data template.
Start the animations where ever you want.
Alternative: Without creating a new user control you can specify animations by creating storyboard and applying required transformations. this gives a common animation to all the list box items.
I am trying to do a simple example of the typical slider.value binded to a textblock. I have tried to maintain it so simple that I cannot find what would be the problem here.
I have this simple XAML code and NO code behind:
<phone:PhoneApplicationPage
.......
.......
.......
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Slider x:Name="mySlider" />
<TextBlock Text="{Binding ElementName=mySlider, Path=Value, Mode=OneWay}" />
</Grid>
</phone:PhoneApplicationPage>
With this code, the slider movement is locked. If I remove the TextBlock binding then all works fine (but no value on TextBlock, of course) :-)
It seems so simple that I know something very, very stupid is locking my brain.
I have tried the 'Binding' in anyway you can imagine, but no luck at the moment.
Any help and any explanation, please ?
Try setting maximum and minimum properties on your slider.
OK, try a stackpanel for your layout:
<StackPanel x:Name="LayoutRoot" Background="White">
<Slider x:Name="mySlider" />
<TextBlock Text="{Binding ElementName=mySlider, Path=Value, Mode=OneWay}" Height="30" />
</StackPanel>
I think the issue is that your controls are sitting on top of each other.
I have created a listbox which has a horizontal orientation. When I load the content, in the stackpanel the size of stackpanel will automatically adjust to the size of the content stored inside. How do I achieve this in a listbox?
This is my listboxcode in XAML:
<ListBox Name="WebScrollView"
Grid.Row="2"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
SelectionMode="Multiple"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch" >
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Height" Value="Auto" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Top"
HorizontalAlignment="Center"
/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
WebBrowser is a very expensive control for both CPU and memory. Creating a separate instance of a WebBrowser for each item in a ListBox seems like a bad idea for that reason alone. I suggest that you use the Html Agility Pack to extract the fields you want and bind them into TextBlocks and other controls. You'll also gain much greater control over the display of each item.
http://htmlagilitypack.codeplex.com/
I have a design issue with my listbox on my view.
Currently it has following DataTemplate as ItemTemplate:
<DataTemplate x:Key="MovieItemTemplate">
<StackPanel>
<Border BorderBrush="{StaticResource PhoneForegroundBrush}" BorderThickness="5" Margin="3" Height="215" Width="140">
<Image x:Name="MovieCover"
toolkit:TiltEffect.IsTiltEnabled="True"
Margin="0"
HorizontalAlignment="Center"
Width="140"
Height="210">
<Image.Source>
<BitmapImage UriSource="{Binding Cover}" CreateOptions="BackgroundCreation"/>
</Image.Source>
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="Tap">
<gsextra:EventToCommand Command="{Binding MainViewModel.MovieItemSelectedCommand, Source={StaticResource Locator}}"
PassEventArgsToCommand="True"
CommandParameter="{Binding MovieID}"
></gsextra:EventToCommand>
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
</Image>
</Border>
</StackPanel>
</DataTemplate>
So as you can see, I have an image inside it that will download his content from the internet through an URI. Thanks to the new mango option BackgroundCreation ( cfr. http://blogs.msdn.com/b/slmperf/archive/2011/06/13/off-thread-decoding-of-images-on-mango-how-it-impacts-you-application.aspx ) it load in background.
But I have a very large collection and even though I do 'paged' binding of the Listbox Source, I notice my memory keeps on going up, until it has consumed everything and the app crashes.
Then, I noticed this http://blog.wpfwonderland.com/2011/01/17/images-and-memory-leaks-in-windows-phone-7/ so it would seem I need to cleanup the image itself, because of the image caching feature in wp7.
When I do this, everything works great in reference to memory, BUT now each time the user 'pages' through the listbox the images need to be redownloaded, resulting in an app that is almost not usable... because the user keeps on waiting for those images.
Any tips/tricks on how to go about this?
I also tried the DefferedLoadListBox