i am accessing the google books api to display thumbnail images in my book result page in my app.The thing i want to do is when the user access the books list immediately i want to show a 'loading' png image from my image folder as it will take some time for the thumbnail to load from the google books api. then one by one the original thumbnail image will load over the loading images giving the user the nice experience. the thing is that how can i rebind the images(i.e after loading the loading images i want to load the real thumbnail)?. here is the relevant code. any idea how can i do it in an appropriate way?
if using converters i am not sure how can i identify which image to show when?
<DataTemplate x:Key="BooksItemTemplate">
<Grid Margin="{StaticResource PhoneTouchTargetOverhang}" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Click="Button_Click_1" />
<Image Source="Images/loading.jpg" Height="150" Width="150"/>
<StackPanel Grid.Column="1" VerticalAlignment="Top">
<TextBlock Text="{Binding BookTitle}" Style="{StaticResource PhoneTextNormalStyle}" TextWrapping="Wrap" FontFamily="{StaticResource PhoneFontFamilySemiBold}"/>
<TextBlock Text="{Binding Identificationno}" Style="{StaticResource PhoneTextNormalStyle}" TextWrapping="Wrap" FontFamily="{StaticResource PhoneFontFamilySemiLight}"/>
</StackPanel>
</Grid>
</DataTemplate>
<phone:LongListSelector x:Name="bookslist"
Background="Transparent"
IsGroupingEnabled="False"
ItemTemplate="{StaticResource BooksItemTemplate}"/>
public BookCategoriesViewModel bookcategoriesvm;
public BooksListing()
{
InitializeComponent();
bookcategoriesvm = new BookCategoriesViewModel();
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string categoryid = string.Empty;
if (NavigationContext.QueryString.TryGetValue("catid", out categoryid))
{
bookcategoriesvm.GetBookcategories(Convert.ToInt64(categoryid));
}
bookslist.ItemsSource = bookcategoriesvm.BooksCategoriesList;
}
The easiest is probably just to have two Image on top of each other (the "loading image" at the bottom) like this whenever the thumbnail is finished downloading, it will just hide your loading image.
Related
I have a simple application with two pages on it. The first page acts normally, and I have a button on the page that navigates to the second page.
However, when I get to the second page, any time I try to touch anything, the OnTouch event fires and an ArgumentException is thrown in the ListDictionaryInternal
However, I have nothing on the page that interacts with this OnTouch event, so I'm not sure what could be causing it.
The code to navigate to the new page:
string page = "valid";
NavigationService.Navigate(
new Uri("/Dialog.xaml?page=" + page,
UriKind.Relative)
);
The XAML of the page that crashes is very simple:
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Name="AppName" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Name="PageName" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle2Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Button Click="CancelDownload_Click" Opacity="1.0" Content="Cancel REST Request!" Background="Blue" Foreground="White" BorderBrush="Black" FontWeight="Bold" BorderThickness="1" x:Name="CancelData" VerticalAlignment="Center" Margin="90,327,90,291" Height="150" Width="300" Visibility="Collapsed" />
</Grid>
</Grid>
What could be causing the OnTouch to fail in such a way?
Thank you for any help.
As it turns out, thee was a hack from the main page I had used to disable the scrolling of PivotItems when interacting with a nested Panorama.
The code that caused the error:
Touch.FrameReported += (s, e) =>
{
if (e.GetPrimaryTouchPoint(MainItems).Action == TouchAction.Up)
{
MainItems.IsHitTestVisible = true;
}
};
I'm writing a Windows Phone application that shows a number of locations on a map. These positions have phone numbers, twitter accounts and websites associated with them.
What I want to do is add a context menu to the items that allows the user to open the websites, view twitter or call the phone number. However, with a MapItemsControl their is no easy way to get the current item.
I am looking for some way to do this in as painless a way as possible.
Some code:
<mi:MapItemsControl x:Name="mapPins" ItemsSource="{Binding Pushpins}">
<mi:MapItemsControl.ItemTemplate>
<DataTemplate>
<mi:Pushpin Location="{Binding Location}">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu IsEnabled="{Binding ShowContext}" >
<TextBlock Opacity="{Binding Opacity, ElementName=image}" Text="Show Menu"/>
<TextBlock Opacity="{Binding Opacity, ElementName=image1}" Text="Open Webpage" Tap="EOpenWeb" />
<StackPanel Opacity="{Binding Opacity, ElementName=image2}" Orientation="Horizontal" Tap="ECallPhone">
<TextBlock Text="Call "/>
<TextBlock Text="{Binding Contact.FormattedPhone}"/>
</StackPanel>
<TextBlock Opacity="{Binding Opacity, ElementName=image3}" Text="On Twitter" Tap="EOpenTwitter" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<StackPanel HorizontalAlignment="Stretch">
<TextBlock Foreground="{Binding Foreground}" Text="{Binding Name}" d:LayoutOverrides="HorizontalAlignment"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,-6" Visibility="{Binding ShowGlyphs}">
<TextBlock TextWrapping="Wrap" Text="{Binding HereNow}" Visibility="{Binding ShowHere}" VerticalAlignment="Center" FontSize="{StaticResource PhoneFontSizeMediumLarge}" HorizontalAlignment="Left" Height="36" Width="48" TextAlignment="Center"/>
<Image x:Name="image" Height="48" Opacity="{Binding HasMenu}" Source="locationGlyphs/appbar.book.open.png" Stretch="Fill"/>
<Image x:Name="image1" Height="48" Opacity="{Binding HasWeb}" Source="locationGlyphs/appbar.link.png" Stretch="Fill" Width="48"/>
<Image x:Name="image2" Height="48" Opacity="{Binding HasPhone}" Source="locationGlyphs/appbar.phone.png" Stretch="Fill" Width="48"/>
<Image x:Name="image3" Height="48" Opacity="{Binding HasTwitter}" Source="locationGlyphs/appbar.twitter.bird.png" Stretch="Fill" Width="48"/>
</StackPanel>
</StackPanel>
</mi:Pushpin>
</DataTemplate>
</mi:MapItemsControl.ItemTemplate>
</mi:MapItemsControl>
That details how the objects are drawn to the map. The Pushpins list is just an Observable Collection of my data.
If this was a ListBox I could simply use the SelectedItem or similar to resolve this, but that doesn't seem an option for MapItemsControl. Has anyone managed to do this successfully? How?
You need to somehow react to the tap on the pushpin. You have a contextmenu and you clearly need to go that way at the moment. needs to have a tap event handler attached:
<mi:Pushpin
Location="{Binding Location}" Tap="Pushpin_Tap">
Pushpin_Tap event handler needs to be managed similar to this:
private void Pushpin_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
var _ppmodel = sender as Pushpin;
ContextMenu contextMenu =
ContextMenuService.GetContextMenu(_ppmodel);
contextMenu.DataContext = _viewModel.Pushpins.Where
(c => (c.Location
== _ppmodel.Location)).FirstOrDefault();
// this way you can find which pushpin/position was tapped by finding the
// one which has the same location in your Pushpins observable collection
if (contextMenu.Parent == null)
{
contextMenu.IsOpen = true;
}
}
I wrote about showing a context menu on pushpin tap on my blog, so if you wish you can go and read the whole story there.
I have a Panorama control, which has an ExpanderView Item (from Silverlight toolkit).
My client wants this page to be customizable. Thats why I created 3 level of binding:
The PanoramaItems, the ExpanderView headers and the ExpanderView content.
The problem when I set the itemssource of the Panorama control. it takes about 5 seconds to show the items.
Any idea how I can solve this?
C# code:
private void panorama_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = App.Products;
}
XAML Code:
<controls:Panorama Loaded="panorama_Loaded" x:Name="panorama" ItemsSource="{Binding}">
<controls:Panorama.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding Sub_Products}" >
<ListBox.ItemTemplate>
<DataTemplate>
<toolkit:ExpanderView Header="{Binding}" Expander="{Binding}" ItemsSource="{Binding Sub_Sub_Products}">
<toolkit:ExpanderView.ExpanderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image VerticalAlignment="Center" Source="Images/List.png" Width="25" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</toolkit:ExpanderView.ExpanderTemplate>
<toolkit:ExpanderView.ItemTemplate>
<DataTemplate>
<Grid Margin="-30,0,0,0" Background="White" Width="450" Tap="Grid_Tap" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="{Binding ImageSource}" />
<StackPanel VerticalAlignment="Top" Grid.Column="1">
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Description}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
<TextBlock Margin="0,12,32,0" Grid.Row="1" Text="Learn more" />
</StackPanel>
</Grid>
</DataTemplate>
</toolkit:ExpanderView.ItemTemplate>
</toolkit:ExpanderView>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</controls:Panorama.ItemTemplate>
</controls:Panorama>
You could try to collapse the panorama items that are off screen and only set visibility to visible on demand. That should at least reduce the size of the visible tree.
A good way to find the slow parts is to use the profiler in Visual Studio. You will find one frame which is really slow (it will have a render time of 5 seconds in your case). Then dig into the visual tree of that frame and see which elements took a long time to render and try to optimize these.
Remove the ExpanderView ItemsSource binding in xaml and bind to it when the Expander is manupulated in code. Just leave it as ItemsSource="{Binding}". That way you will dynamically build you visual tree as the user taps on the expander.
The event handler is something like below. I am assuming Product is the type in your App.Products list. Also ensure that you hook up the event in your xaml for the expander.
private void ExpanderView_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
var expander = sender as ExpanderView;
expander.ItemsSource = (expander.DataContext as Product).Sub_Sub_Products;
}
Hope this solves your slow loading issues and is not too late at this time.
I am using a Expander View in my MainPage that is Bind to a collection of "Account Categories" (each item in this collection has further a collection of Accounts)
The Bindings are all working fine, with a small glitch though. There is another page Where a user can Add new Accounts (Thus changing Accounts & Account Categories) now when I navigate back to the Main Page the Expander Control does not show updated values?
The binding is done on OnNavigatedTo event of the Main Page
The DataBase context file is generated by Sql Metal tool
(More on this here Using SQl Metal to generate DB files for wp7)
That means all my classes implement INotifyChanging & INotifyChangedEvents
Here is the XAML & C# code
private WalletDataContext context;
private ObservableCollection<AccountCategory> _accountCategories;
public ObservableCollection<AccountCategory> AccountCategories
{
get { return _accountCategories; }
set
{
if (_accountCategories != value)
{
_accountCategories = value;
NotifyPropertyChanged("AccountCategories");
}
}
}
public MainPage()
{
InitializeComponent();
//Initialize Data context
context = new WalletDataContext(WalletDataContext.DBConnectionString);
//Set page data context
this.DataContext = this;
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
//fetch all existing Account Categories
var accountCategoriesInDB = (from AccountCategory acctCat in context.AccountCategory
select acctCat);
//Update Page Collection
AccountCategories = new ObservableCollection<AccountCategory>(accountCategoriesInDB);
this.listBox.ItemsSource = AccountCategories;
base.OnNavigatedTo(e);
}
Here are the XAML bindings
<ListBox Grid.Row="0" x:Name="listBox">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<toolkit:ExpanderView Header="{Binding}" Expander="{Binding}"
ItemsSource="{Binding Accounts}"
HeaderTemplate="{StaticResource CustomHeaderTemplate}" ExpanderTemplate="{StaticResource CustomExpanderTemplate}">
<toolkit:ExpanderView.ItemTemplate>
<DataTemplate>
<Grid VerticalAlignment="Center" Height="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="0.105*"/>
<RowDefinition Height="0.105*"/>
<RowDefinition Height="0.789*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.366*"/>
<ColumnDefinition Width="0.634*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding AccountNumber}" Style="{StaticResource PhoneTextNormalStyle}" VerticalAlignment="Center" HorizontalAlignment="Left"></TextBlock>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Balance}" Style="{StaticResource PhoneTextSubtleStyle}" VerticalAlignment="Center" HorizontalAlignment="Left"></TextBlock>
</Grid>
</DataTemplate>
</toolkit:ExpanderView.ItemTemplate>
</toolkit:ExpanderView>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Any ideas on whats wrong?
Thanks for your help in advance..
The MainPage reloads the data from the context in the OnNavigatedTo method.
Make sure you save/mark the updated data to the context in the Add New Account page.
Trying to find the sexiest way to receive a "tweet" from the twitter API and find any urls that may exist in it and then making those links "clickable" inside the displayed tweet. Was thinking of doing it exactly as the official twitter app does it when you click on a tweet and go to the page that details that particular tweet and the url inside the tweet is bold and blue and clickable....
example of the data I'm working with...
https://dev.twitter.com/docs/api/1/get/statuses/show/%3Aid
Not sure if I should take the string that is returned and parse through it to find something starting with "http:" or "https:" or if I should loop through the URL array that is returned in the tweet object from twitter (in which case I would then need to find the same string in the message string and change it into a link anyway)...
Also, which control should I use for the link, should I programmatically insert a button into the textblock? Is there a way to make part of a textblock clickable?
I know there is an elegant and simple solution to this that I'm missing. My layout is below:
<Grid x:Name="LayoutRoot">
<Grid.Background>
<ImageBrush ImageSource="pageBackground.png"/>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<StackPanel Orientation="Horizontal" Margin="12,0,0,0">
<Image Source="{Binding profile_image_url}" Height="83" Width="83" VerticalAlignment="Top" />
<StackPanel Width="371">
<TextBlock Text="{Binding name}" TextWrapping="Wrap" Foreground="#066d96" Style="{StaticResource PhoneTextTitle2Style}"/>
<TextBlock Text="{Binding screen_name}" TextWrapping="Wrap" Foreground="#066d96" Style="{StaticResource PhoneTextTitle2Style}"/>
</StackPanel>
</StackPanel>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<TextBlock Text="{Binding text}" Name="tbText" Foreground="#211F20" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" />
<TextBlock Text="{Binding age}" TextWrapping="Wrap" Foreground="#fabb69" Style="{StaticResource PhoneTextSubtleStyle}" Padding="0 10 0 0"/>
</StackPanel>
</Grid>
</Grid>
I can't answer for the non-Twitter API parts, but if you set Twitter's include_entities parameter to true, t, or 1 (as detailed on the documentation page you linked to), you'll get a pre-parsed representation of the tweet back.
If you look at the example in the documentation, entities is an object containing a urls array. Each object in the urls array is a URL. The indices array in the URL object contains the starting and ending index of the URL in the tweet text.