Windows Phone 8 Hubtile Source and Background Image Loading - windows-phone-8

Currently we are using the HubTile to display a large (50-70) images and text overlayed.
<toolkit:HubTile Margin="0,12,12,0"
Title="{Binding title}"
Message="{Binding itemLink}"
Source="{Binding media}"
GroupTag="BindingHubTile"
Style="{StaticResource HubTileStyle1}">
</toolkit:HubTile>
<TextBlock Height="Auto" FontSize="14" FontFamily="{StaticResource PhoneFontFamilyLight}"
TextWrapping="Wrap" Text="{Binding votes}" TextTrimming="WordEllipsis" VerticalAlignment="Bottom"
Foreground="{StaticResource PhoneForegroundBrush}" TextAlignment="Right" Margin="0,0,15,-7" />
The source is bound to a URI that is retrieved from a webserver which then allows the phone to download the image and display it. The problem is, with this amount of images we are finding that the UI is locking up.
Our hubtiles are loaded into a listbox by means of listbox.ItemSource.
Is there an easy way around this?

When you set to an image - URI it downloads in background and doesn't lock the UI - tested.
The only thing that remains is to find where you have locked it.
I had a similar project, but i created CustomControls to fill ListBox. Custom Control contained - date field, text and image.
Image was loaded like this:
BitmapImage image = new BitmapImage(new Uri(article.ImageURL));
NLBI.Thumbnail.Source = image;
And all images were loading async in background and UI was usable.

Related

Create Tab Items and Tab Content dynamically using Orchestra/Catel

I am attempting to create a tabbed interface using Orchestra/Catel. I load the tabs definitions into a TabInfo class. Those work fine - a tabbed interface is created with the correct tab descriptions. In the content for each tab, I want to create a list of buttons - again loaded into a ButtonInfo class. When a tab is selected, the SelectedTab property is used to select the correct list of buttons (ShowButtons).
I have traced the program and when I click on a tab, the correct collection of buttons is in ShowButtons, but nothing shows up in the tab content. I did get this to work in a normal MVVM program, but without the tabs. I used a listview to show my tabs and an ItemsControl to show the buttons.
Belows is my XAML code for the tabs and my SelectedTab logic for pulling the buttons.```
<Grid>
<orccontrols:TabControl LoadTabItems="LazyLoading" ItemsSource="{Binding TabInfo}" SelectedItem="{Binding SelectedTab}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TabDesc}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding ShowButtons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding ButtonDesc}"
MinWidth="150"
Height="30"
FontSize="12"
FontWeight="Bold"
Margin="0,15,25,10"
Padding="5,1">
<Button.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding OracleJob}" Value="0">
<Setter Property="Button.Background" Value="DarkSalmon" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</TabControl.ContentTemplate>
</orccontrols:TabControl>
</Grid>
And the code for populating ShowButtons:
public void OnSelectedTabChanged()
{
int _selectTab = SelectedTab.TabKey;
var _showButtons = ButtonInfo.Where(i => i.ButtonTab == _selectTab);
ObservableCollection<ButtonRecord> _btn = new ObservableCollection<ButtonRecord>(_showButtons);
ShowButtons = _btn;
}
Any help is greatly appreciated. I am a beginner with Orchestra/Catel, so I am probably missing the best way to do this.
I recommend to split up the issue from Orchestra / Catel. Orchestra allows you to provide a view as shell, but this view can live on it's own (the only thing Orchestra does is place it inside the correct location inside the shell). By making this problem unrelated to Orchestra, it makes it a bit easier for us to solve.
Next up, I recommend looking into the Catel docs. There is a full example on how to show a shell with tabs with closable tab buttons, see https://docs.catelproject.com/vnext/tips-tricks/mvvm/using-tabbed-interface-with-mvvm/

Panorama-control don't remember selected panorama item when navigating

I'm using a panorama control in my wp8 app that consists of 4 panorama-items. These items are all i separate files. The content within the items are bound to viewmodels, (using MVVM Cross).
The problem is when I navigate from a panorama-item to a new page and go back, the panorama control shows the first panorama-item (it kinda resets).
I've tried to override OnNavigatedTousing the selectedIndexon the panorama control, but it only returns -1.
The xaml class containing the panorama-control:
<Grid x:Name="LayoutRoot" Background="Transparent">
<!--Panorama Control-->
<!--Cannot bind directly to background with ImageBrush, using converter instead-->
<controls:Panorama x:Name="panorama"
Background="{Binding Home.WindowsBackgroundUrl, Converter={StaticResource ImageBrushConverter}}">
<controls:Panorama.Title>
<StackPanel Orientation="Vertical" Margin="0,60,0,0">
<Image x:Name="Icon" Source="/Images/PanoramaLogo.png" />
</StackPanel>
</controls:Panorama.Title>
<!--Panorama items-->
<ScrollViewer>
<local:InterestView x:Name="Interest" Margin="0,-20,0,0" />
</ScrollViewer>
<ScrollViewer>
<local:CustomerCategoryPanoramaItem x:Name="Customer" Margin="0,-20,0,0"/>
</ScrollViewer>
<ScrollViewer>
<local:MapListView x:Name="MapList" Margin="0,-20,0,0"/>
</ScrollViewer>
<ScrollViewer>
<local:ContactMeView Margin="0,-20,0,0"/>
</ScrollViewer>
</controls:Panorama>
</Grid>
Thanks for any help
If you are persisting your screen in view stack than it panorama-control will take care of that other-vice we have to persist selected panorama while we are navigating forward and when we come back to Panorama control. For that we has to set its DefaultItem property .
Panorama numbers its view starting from 0, Like for if we have three panorama Items than it will give 0 to first, 1 to second and 2 to third.
Example :
PanoramaControl.DefaultItem = PanoramaControl.Items[0 to 2];

Background thread to download image and set to image view

In my windows phone 8 application, i have one image view, by default it is set to local static image.
<Image x:Name="advImage" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Source="Images/banner.jpg" Stretch="Fill" Margin="0,0,0,0"/>
Now after loading the page, I want to get the original image from the server and should be replace the above static image. This task should be done in background via thread so that the user interface should not be blocked. I don't want to display any progress bar while downloading the image.
I'm new to windows phone 8. Please provide your solutions to the problem.
Thanks.
You need too use databinding(binding)
<Image x:Name="advImage" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Source="'Binding Image,mode=twoway" Stretch="Fill" Margin="0,0,0,0"/>
private string _image;
public string Image{
get
{
return m_IconPath;
}
set
{
_IconPath = value;
PropertyChanged ("IconPath");
}
}
Now when your user is connected get your server image and set the property Image.

How to free memory hold by images in data template in windows phone 8 App?

I have a longlistselector for which I have a data template that defines the type of items to be added to the list. The data template has an Image control whose source is binded with path dynamically, thus each item in list has an associated Image Control. The problem I face is that these Image control never free the memory they occcupy resulting in out of memory exception. On normal scenario I set bitmapImage.UriSource=null to deallocate the memory associated with the bitmap But can't find a way to do so in this scenario. Here is the xaml code for the longlistselector and the data template associated with it..
Data Template
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="MediaItemTemplate">
<Canvas VerticalAlignment="Top">
<Border BorderBrush="#FF4791CA" BorderThickness="3">
<Image Height="100" Width="100" VerticalAlignment="Top" Grid.RowSpan="2" Stretch="UniformToFill">
<Image.Source>
<BitmapImage UriSource="{Binding path}" CreateOptions="BackgroundCreation" DecodePixelHeight="50" DecodePixelWidth="50"/>
</Image.Source>
</Image>
</Border>
<Image Source="/Icons/check.png" Height="16" Width="16" Grid.Row="0" Grid.Column="0" VerticalAlignment="Top" Margin="80,7,7,0" Canvas.ZIndex="100" OpacityMask="Black" Visibility="{Binding visibility}" Name="checkImage" >
</Image>
</Canvas>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
LonglistSelector
<phone:LongListSelector
Tap="ListMedia_Tap"
x:Name="ListMedia"
HorizontalAlignment="Left"
Height="624"
VerticalAlignment="Top"
Width="436"
Background="Transparent"
ItemTemplate="{StaticResource MediaItemTemplate}"
LayoutMode="Grid" GridCellSize="120,120"/>
I am very new to windows phone programming, What basically I want to do is to develop kind of image browser experience. Please Help me out with ways to deallocate the memory. In case I am doing it completely wrong please correct me or suggest better ways to achieve the same functionality. Thanx in advance...
A solution I've found to handle this case is making a custom control to automatically set the urisource to null:
public class SafePicture : System.Windows.Controls.ContentControl
{
public SafePicture()
{
this.Unloaded += this.SafePictureUnloaded;
}
private void SafePictureUnloaded(object sender, System.Windows.RoutedEventArgs e)
{
var image = this.Content as System.Windows.Controls.Image;
if (image != null)
{
image.Source = null;
}
}
}
Then, just wrap all your pictures in that control:
<my:SafePicture>
<Image Source="{Binding Path=path}" />
</my:SafePicture>
By default Windows Phone stores messages downloaded from a Uri in memory to save having to load them again. (It's a crude form of caching.)
To free the memory used by these images you needed to explicitly free all references to them. See MSDN: Image Tips for Windows Phone 7 for more details
When scrolling with your code (without using Loaded), then images are lost after scrolling down and returning to the top of the list (speed no matter). While using Loaded, scrolling wokrs okay: it is possible to scroll down and return to the top, (debugger shows that Unloaded and Loaded are called), and images are there. However, when moving to another page (i have master-detail pages), they are mixed up.

Accessing named controls from page resources

I needed to access to the ActualWidth of a Border that didn't have a specified Width. I have been told that I can't do that on WinRT so I used a proxy from Florian-Gl (from here).
The thing is that I need to create that proxy on the page's resource like this:
<Page.Resources>
<utils:ActualSizePropertyProxy Element="{Binding ElementName=noteBorder}" x:Name="proxy" />
</Page.Resources>
The problem is that I don't have access to that noteBorder element from the resources, but I have access to pageRoot that is the Page itself.
I guess that I can play with ElementName / Path to get access to noteBorder.
But there is some curious stuff:
The structure is something like:
Page (pageRoot) > Grid > ListView > ListView.ItemTemplate > Grid > Border (noteBorder)
So, If I create the proxy at the same level of the border, It won't run but If I change the ListView to a ItemsControl, it will run and works as expected.
If having it at the same level of the border I change the ElementName to pageRoot it will run at least.
So, It won't run if I put noteBorder (even when I have access to it) if I'm using a ListView, but will work on a ItemsControl, On the other hand, If I have pageRoot it works all ways.
So the question is: Is there a way to access noteBorder from resources? Or maybe a way to access it from another place but working :P
You should be using an Item Template --
By the time you get to
pageRoot) > Grid > ListView or Items Control
At this point in the structure, you're at the element you really want to get at, which is the container of the items that will need the border you are trying to access.
You should define an Item Template and assign the ListView's (or ItemsControl's) ItemTemplate property via binding.
<ListView x:Name="myListView" DataContext="{Binding ToElementIfNotInheritedFromParent}" ItemsSource="{Binding ViewModelListBeingBoundTo}" ItemTemplate="{Binding Source={Static Resource MyCustomItemTemplate}}" />
Where MyCustomItemTemplate is something like
<DataTemplate x:Name="MyCustomItemTemplate">
<Border x:Name="myBorder" >
<StackPanel>
<TextBlock Text="{Binding Path=Title}" />
<TextBlock Text="{Binding Path=FirstProperty}"/>
<TextBlock Text="{Binding Path=SecondProperty}"/>
</StackPanel>
</Border>
</DataTemplate>
Then In your Codebehind (or if ViewModel use the code behind to pass the ListView object to the ViewModel)
DataTemplate dt = this.myListView.Items[indexOfChoice].ItemTemplate as DataTemplate;
Border b = dt.LoadContent() as Border;
int actualWidth = b.AcutalWidth
OR
You can create a FindControl() method that runs recursively to extract the actual control within the border, for instance if you wanted to access one of the Textboxes.
The code for that is here:
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/a612f5a6-e05e-4b68-a813-893eeda159cc