WP8 get URI of images in MediaLibrary - windows-phone-8

As I am using my own LongListSelector to let the user select from an image I need to retrieve the URI's of all images in the Medialibrary. I couldn't find any possibility to do this yet.
All I have seen what is possible is to get the name of the image:
MediaLibrary m = new MediaLibrary();
foreach (var r in m.Pictures)
{
Stream imageStream = r.GetImage();
}
How can I get the rest of the path?
EDIT
Following the first solution:
Gallery.xaml
<phone:LongListSelector
x:Name="GalleryLLS"
LayoutMode="Grid"
GridCellSize="108,108"
SelectionChanged="GalleryLLS_SelectionChanged"
Margin="0,0,144,12"
ItemsSource="{Binding ListOfImages}" >
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Width="150" Height="150"
Source="{Binding}"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
Gallery.xaml.cs
private List<WriteableBitmap> _listOfImages = new List<WriteableBitmap>();
public List<WriteableBitmap> ListOfImages
{
get { return _listOfImages; }
set { _listOfImages = value; }
}
public Gallery()
{
InitializeComponent();
var ml = new MediaLibrary();
var Pictures = ml.Pictures;
foreach (var item in Pictures)
{
ListOfImages.Add(PictureDecoder.DecodeJpeg(item.GetImage()));
}
}
results in not showing images. Debugger shows that imageas are added correctly to my list but I won't see anything.

It seems that the API doesn't exposes URI property for pictures returned from Media Library. So you need to do it with different approach. For example, you can have a list of WritableBitmaps instead of list of URIs :
private List<WriteableBitmap> _listOfImages = new List<WriteableBitmap>();
public List<WriteableBitmap> ListOfImages
{
get { return _listOfImages; }
set { _listOfImages = value; }
}
.......
.......
var ml = new MediaLibrary();
var Pictures = ml.Pictures;
foreach (var item in Pictures)
{
ListOfImages.Add(PictureDecoder.DecodeJpeg(item.GetImage()));
}
........
//in XAML
<phone:LongListSelector ItemsSource="{Binding ListOfImages}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Width="150" Height="150"
Source="{Binding}"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
........
</phone:LongListSelector>
........
[Codes adapted from http://www.neelesh-vishwakarma.com]

Why do you need the path? To show the image? If you just need to show the image in the list as a thumbnail, you can use the stream to create a BitmapImage:
var bi = new BitmapImage();
bi.SetSource(r.GetThumbnail());
Now you can set that bi as a Image.Source.

Related

Download image in windows phone 8.1

i want to download images from specified Uri s and show it in Grid View
<GridView>
<GridView.ItemTemplate>
<DataTemplate>
<Image Width="150" Height="150" Source="{Binding Source={}}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
If you have a model class, set the following property & bind it to the image element.
Public class YourClass
{
public string imageuri { get ; set ; } //web image uri
public BitmapImage ImageUrl
{
get
{
if (!string.IsNullOrEmpty(imageuri))
{
BitmapImage bmi = new BitmapImage();
bmi.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bmi.UriSource = new Uri(imageuri, UriKind.Absolute);
return bmi;
}
return null;
}
}
}
<GridView>
<GridView.ItemTemplate>
<DataTemplate>
<Image Width="150" Height="150" Source="{Binding ImageUrl,Mode=Twoway}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>

Using FlipView to create TabControl in Metro Apps

i'm currently creating a Metro Style Application and want to use the FlipView control to work like the tab control in WPF and winforms, please can any one help me ?
You would put FlipViewItems in the FlipView the same way you'd put TabItems in a TabControl. To add tabs - you could have a StackPanel with TextRadioButtonStyled RadioButtons that have their check states synchronized with the FlipView selection state. Alternatively you could have a heavily styled ListView for the headers bar.
i solved it by editing the flipviewitem template and making its view like the wanted tab page view. Then i added a button on the top of every item to activate it.
We don't have Tab Control in WP8.1 but we can customize using FlipView. Flip View has a property selected index so we can set which view we want.
Create a xaml page, for example MainPage.xaml
For Tab Header
<Border BorderThickness="0,0,0,1" BorderBrush="White" >
<Grid Grid.Row="0" Background="Black" x:Name="navigateHead" >
<TextBlock x:Name="appbarSports" Text="Sports" Tapped="appbarSports_Tapped" TextAlignment="Center" Width="80" Margin="0,34,320,7" />
<TextBlock x:Name="appbarCars" Text="Cars" Tapped="appbarCars_Tapped" Margin="160,34,160,7" TextAlignment="Center" />
<TextBlock x:Name="appbarHomes" Text="Homes" Tapped="appbarHomes_Tapped" Margin="80,34,240,7" TextAlignment="Center" />
<Image x:Name="imgLine0" Source="ms-appx:///Images/white.png" Width="80" Height="3" Stretch="Fill" Margin="0,55,320,1" ></Image>
<Image x:Name="imgLine1" Source="ms-appx:///Images/white.png" Width="80" Height="3" Stretch="Fill" Margin="81,55,239,1" Visibility="Collapsed" />
<Image x:Name="imgLine2" Source="ms-appx:///Images/white.png" Width="80" Height="3" Stretch="Fill" Margin="162,55,158,1" Visibility="Collapsed" />
</Grid>
</Border>
For Flip view XAML code is
<Grid Grid.Row="1" >
<FlipView x:Name="flipControl" SelectionChanged="flipControl_SelectionChanged" >
<FlipViewItem >
<ListView x:Name="listViewForSports" >
<ListView.ItemTemplate>
<DataTemplate>
<Image Stretch="Fill" Source="{Binding SportsImage}"></Image>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</FlipViewItem>
<FlipViewItem >
<ListView x:Name="listViewForHomes">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding HomesImage}" Stretch="Fill"></Image>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</FlipViewItem>
<FlipViewItem >
<ListView x:Name="listViewForCars">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding CarsImage}" Stretch="Fill"></Image>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</FlipViewItem>
</FlipView>
</Grid>`
and write in code behind file MainPage.xaml.cs
Just initialize these globally:
public sealed partial class MainPage : Page
{
List<Sports> listOfSports;
List<Cars> listOfCars;
List<Homes> listOfHomes;
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
bind data to the FlipView control when page is initialized
protected override void OnNavigatedTo(NavigationEventArgs e)
{
flipControl.SelectedIndex = 0;
// TODO: Prepare page for display here.
// TODO: If your application contains multiple pages, ensure that you are
// handling the hardware Back button by registering for the
// Windows.Phone.UI.Input.HardwareButtons.BackPressed event.
// If you are using the NavigationHelper provided by some templates,
// this event is handled for you.
GetData();
}
This method will bind
public void GetData()
{
listOfSports = new List<Sports>();
for (int i = 1; i < 9; i++)
{
listOfSports.Add(new Sports() { SportsImage = #"ms-appx:///Images/Sports/image" + i.ToString() + ".jpg" });
}
listViewForSports.ItemsSource = listOfSports;
listOfCars = new List<Cars>();
for (int i = 1; i < 14; i++)
{
listOfCars.Add(new Cars() { CarsImage = #"ms-appx:///Images/Cars/image" + i.ToString() + ".jpg" });
}
listViewForCars.ItemsSource = listOfCars;
listOfHomes = new List<Homes>();
for (int i = 1; i < 9; i++)
{
listOfHomes.Add(new Homes() { HomesImage = #"ms-appx:///Images/Homes/image" + i.ToString() + ".jpg" });
}
listViewForHomes.ItemsSource = listOfHomes;
}
public class Cars
{
public string CarsImage { get; set; }
}
public class Sports
{
public string SportsImage { get; set; }
}
public class Homes
{
public string HomesImage { get; set; }
}`
I did with tap event to navigation withing flip view` private void appbarSports_Tapped(object sender, TappedRoutedEventArgs e)
{
// TextBlock a = sender as TextBlock;
// imgLine0.Margin = new Thickness(a.Margin.Left, 55, a.Margin.Right, 1);
flipControl.SelectedIndex = 0;
method(0);
}
private void appbarCars_Tapped(object sender, TappedRoutedEventArgs e)
{
// TextBlock a = sender as TextBlock;
//imgLine0.Margin = new Thickness(a.Margin.Left, 55, a.Margin.Right, 1);
flipControl.SelectedIndex = 2;
method(2);
}
private void appbarHomes_Tapped(object sender, TappedRoutedEventArgs e)
{
// TextBlock a = sender as TextBlock;
// imgLine0.Margin = new Thickness(a.Margin.Left, 55, a.Margin.Right, 1);
flipControl.SelectedIndex = 1;
method(1);
}
I also used for when the user flips so I used FlipView.SelectionChanged event
private void flipControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
FlipView viewControl = sender as FlipView;
int a = viewControl.SelectedIndex;
method(a);
}
This method() is help full for changing imageLine position
public void method(int a)
{
if (imgLine0 != null)
{
switch (a)
{
case 0:
imgLine0.Visibility = Visibility.Visible;
imgLine1.Visibility = Visibility.Collapsed;
imgLine2.Visibility = Visibility.Collapsed;
break;
case 1:
imgLine0.Visibility = Visibility.Collapsed;
imgLine1.Visibility = Visibility.Visible;
imgLine2.Visibility = Visibility.Collapsed;
break;
case 2:
imgLine0.Visibility = Visibility.Collapsed;
imgLine1.Visibility = Visibility.Collapsed;
imgLine2.Visibility = Visibility.Visible;
break;
}
}
}

Windows phone 8: get value item of listbox

I have a listbox. Every item has an image and title (binding from my list). When I click an item of the listbox, how do I get the title value of that item.
create an event in ListBox called "SelectionChanged" and map it the method in the code behind of the XAML file. In the .cs file get the value from myListBox.SelectedItem and cast it to your list item type.
EX: in XAML file
<ListBox x:Name="myListBox" ItemsSource="{Binding Items}"
SelectionChanged="myListBox_SelectionChanged">
in xaml.cs file:
private void myListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var mySelectedItem = myListBox.SelectedItem as myObject;
}
I hope this helps.
There are already few similar questions (first, second). I'll try to show you an example (little extending this what #KirtiSagar (if it helps accept his solution as it's the same method) has said):
Let's assume that your ItemClass look like this:
public class ItemClass
{
public Uri ImagePath { get; set; }
public string Tile { get; set; } // I used string as an example - it can be any class
}
And you Bind it to your ListBox like this:
<ListBox Name="myList" Grid.Row="2">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ImagePath}"/>
<TextBlock Text="{Binding Tile}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
It is a very simple example but should show you an overview how it works.
Then in my Page and Constructor I need to add my Collection and subscribe to events:
ObservableCollection<ItemClass> items = new ObservableCollection<ItemClass>();
public MainPage()
{
InitializeComponent();
myList.ItemsSource = items;
myList.SelectionChanged += myList_SelectionChanged;
}
The SelectinChanged event can be used for your purpose in many ways. For example you can use its SelectionChangedEventArgs properties. I will show some methods which will produce the same result. I mixed some things on purpose just to show how it can be done.
private void myList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (myList.SelectedItem != null)
{
string myTile = ((sender as ListBox).SelectedItem as ItemClass).Tile;
// you can also get your item like this - using EventArgs properties:
string myTileToo = ((ItemClass)(e.AddedItems[0])).Tile;
}
// also you can get this by SelectedIndex and your Item Collection
if ((sender as ListBox).SelectedIndex >= 0)
{
string myTileThree = items[myList.SelectedIndex].Tile;
}
}
Note that your LisBox can work in different SelectionModes for example Multipe - you can also try to use that if you need it (there are properties SelectedItems and AddedItems / RemovedItems, which are IList).

Longlist will not update at load

I am having some problems making a long list selector load my data, and i have been unable to find a solution to this problem.
This is my xaml:
<phone:LongListSelector x:Name="animeList"
Margin="0,0,-12,0"
ItemsSource="{Binding Animes}"
Tap="AnimeList_OnTap">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu IsZoomEnabled="false">
<toolkit:MenuItem Header="Add as favorit" Click="AddFavorite" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</TextBlock>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
My view model is simple:
public ObservableCollection<AnimeItemViewModel> _animes { get; set; }
public ObservableCollection<AnimeItemViewModel> Animes
{
get { return _animes; }
set
{
if (value != _animes)
{
_animes = value;
NotifyPropertyChanged("Animes");
}
}
}
And how i load my data:
public MainPage()
{
InitializeComponent();
DataContext = App.ViewModel;
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
ObservableCollection<AnimeItemViewModel> _animes = new ObservableCollection<AnimeItemViewModel>();
foreach (var i in App.AnimeList.List)
_animes.Add(new AnimeItemViewModel() { AId = i.AId, Name = i.Name });
App.ViewModel.Animes = _animes;
}
And lastly just to show that there are data in the list
Update: I also have a search function, and if i enter a search text will the longlist update, but i am for some reason unable to scroll
private void OnKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
ObservableCollection<AnimeItemViewModel> _animes = new ObservableCollection<AnimeItemViewModel>();
foreach (var i in App.AnimeList.List)
if (string.IsNullOrWhiteSpace(SearchTextBox.Text) || i.Name.ToLower().Contains(SearchTextBox.Text.ToLower()))
_animes.Add(new AnimeItemViewModel() { AId = i.AId, Name = i.Name });
App.ViewModel.Animes = _animes;
}
}
Try placing your loading code in OnNavigatedTo. As for the scrolling issue - setting a proper height to the StackPanel. Let me know if it works.

Using a progress indicator that gets hidden within a Panorama control is causing the panorama item to just to 1st one

I have a really strange and annoying issue on my WP8 app.
It's using a Panorama control to view items that it downloads from the Net. It has a view that is displayed whilst it's downloading content but then gets collapsed after the content has completed loading.
When the "loading" view is collapsed I'm finding that the Panorama control jumps back to the first item in the control regardless of what item you have selected.
I have the following very basic test code that demonstrates the issue.
XAML:
<phone:PhoneApplicationPage
x:Class="Wp8.GUI.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="clr-namespace:Wp8.Gui.Converters"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.Resources>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Grid.Resources>
<phone:Panorama ItemsSource="{Binding PanoramaItems}">
<phone:Panorama.HeaderTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<TextBlock Text="{Binding Title}" />
</Grid>
</DataTemplate>
</phone:Panorama.HeaderTemplate>
<phone:Panorama.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel x:Name="Visible1" Visibility="{Binding ShowFirst, Converter={StaticResource BooleanToVisibilityConverter},ConverterParameter=True}" >
<ProgressBar IsIndeterminate="True" />
<TextBlock Text="ShowFirst" />
</StackPanel>
<StackPanel x:Name="Visible2" Visibility="{Binding ShowFirst, Converter={StaticResource BooleanToVisibilityConverter},ConverterParameter=False}" >
<TextBlock Text="Show Second" />
</StackPanel>
</Grid>
</DataTemplate>
</phone:Panorama.ItemTemplate>
</phone:Panorama>
</Grid>
</phone:PhoneApplicationPage>
The VM and Code Behind is as follows:
namespace Wp8.GUI
{
public class PanItemVm : INotifyPropertyChanged
{
private readonly string _title;
private bool _showFirst = true;
public PanItemVm()
{
_title = "Control";
}
public PanItemVm(string title)
{
_title = title;
}
public string Title { get { return _title; } }
public bool ShowFirst
{
get { return _showFirst; }
set
{
_showFirst = value;
RaisePropertyChanged("ShowFirst");
}
}
private void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class PanItemVm2 : PanItemVm
{
public PanItemVm2() : base ("Items")
{
Task.Run(() => Task.Delay(TimeSpan.FromSeconds(5)))
.ContinueWith(t => ShowFirst = false,
TaskScheduler.FromCurrentSynchronizationContext());
}
}
public class TestVm : INotifyPropertyChanged
{
public IEnumerable<PanItemVm> PanoramaItems
{
get {
return Enumerable.Range(0, 2)
.Select(i => i == 0 ?
new PanItemVm() : new PanItemVm2()); }
}
public event PropertyChangedEventHandler PropertyChanged;
}
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
DataContext = new TestVm();
}
}
}
If you run up the code in an emulator and then flick to Item2 in the Panorama. After 5 seconds it'll flick back to the page marked "Control".
In this test code I can get around the problem by either
a) Changing the StackPanel that the ProgressIndicator is contained in to a Grid
b) Removing the ProgressIndicator
Neither of these solutions work for my proper project however but if I remove Visibility code that uses the BooleanToVisibilityConverter then it doesn't flick back.
Does anybody have any ideas what might be causing this?
I can post the entire sample code if that's useful.
Thanks
--- EDIT ---
Here is the code for the BooleanToVisibilityConverter
using System.Windows;
using System.Windows.Data;
namespace Wp8.Gui.Converters
{
public class BooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value is bool)
{
bool visibilityValue = true;
if(parameter != null)
{
if(parameter is string)
{
bool.TryParse((string)parameter, out visibilityValue);
}
}
return (bool)value == visibilityValue ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Visible;
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotImplementedException();
}
}
}
I've been having the same problem. I have a Panorama (modified to fill the full screen) that I'm using to display pictures in a carousel. I have to turn the pictures on/off based on Panorama position to keep the memory low. However, whenever a picture loads, the panorama returns to the default item... the first item.
So I took a hint from another question and went to look at the source code for Panorama. While you can't see the current code, you can see what Panorama was when it was part of the WP Toolkit. It seems that anytime there is a change in size of the panorama, the internal scrollviewer is reset.
void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
// clip to control layout
LayoutRoot.SetValue(Panel.ClipProperty, new RectangleGeometry() { Rect = new Rect(0, 0, this.Width, this.Height) });
// reset scroll viewer
Dispatcher.BeginInvoke(() =>
{
ScrollView.Invalidate(false);
});
}
OK. That was a clue. So I played around with my itemtemplate (my header is non-existent) trying to see what was changing size. SOMETHING was changing size... not sure what. So I wrapped everything in a Grid and hardcoded the Width/Height/MaxWidth/MaxHeight to be equal to the Screen Height/Width. They are bound to calculated values in my viewmodel that change according to device orientation.
<controls:PanoramaFullScreen.ItemTemplate>
<DataTemplate>
<Grid Width="{Binding LayoutWidth}"
MaxWidth="{Binding LayoutWidth}"
Height="{Binding LayoutHeight}"
MaxHeight="{Binding LayoutHeight}">
{rest of stuff}
</Grid>
</DataTemplate>
It works! No more switching back to item one!
So I suspect your code is changing the overall height/width of a PanoramaItem, which is in turn changing the Panorama size and resetting the internal scrollviewer.