Access control in stack panel of listbox - windows-phone-7

I have this xaml
<ListBox x:Name="listBox"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
Tap="listBox_Tap">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Image Name="cPix"
Source="{Binding Image}"
Stretch="None"
Margin="0,0,5,5"
ToolTipService.Placement="Bottom"
ToolTipService.ToolTip="{Binding Name}" />
<TextBlock Text="{Binding Name}"
HorizontalAlignment="Center"
Foreground="Black" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
the concept is that, i want the listbox to lazy load images, there will be a placeholder image first, and while the images finish downloading, the placeholder give way to the downloaded image.
Any help?

You can solve this in your ViewModel. Here is an example pseudo code:
public BitmapImage Image
{
get
{
if (_image == null)
ImageManager.LoadImageAsync(_imageUri).ContinueWith(t=> Image = t.Result);
return _image;
}
set
{
_image = value;
NotifyPropertyChanged("Image");
}
}
Your ImageManager would load images asynchronously, whether from cache, IsolatedStorage or web and when done, it would complete the internal Task.

Related

How to Reference the ViewModel in the View

I am attempting to reference a class in my ViewModel within the xaml of my view, and I am getting an error saying Object reference not set to an instance of an object. THe error occurs when attemping to set the ViewModel as the Resource for a ListBox. Also, when attempting to set the ItemsSource property of my ListBox, another error results stating The resource "effects" could not be resolved.
MainPage.xaml
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.Resources>
//Error occurs here!
<vm:EffectItems x:Key="effects"/>
</Grid.Resources>
//The ItemsSource property thus contains an error as well
<ListBox Name="ListBoxEffects" SelectionMode="Single" ItemsSource="{StaticResource effects}" SelectionChanged="ListBox_SelectionChanged"
toolkit:TiltEffect.IsTiltEnabled="True"
ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Auto">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" ItemWidth="152" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="14,0,0,10" >
<Image Source="{Binding Thumbnail}" Width="128" Height="128" />
<TextBlock Text="{Binding Name}" FontSize="{StaticResource PhoneFontSizeNormal}" VerticalAlignment="Center" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I have also tried the following setup which results in the same errors on the same items
<ListBox Name="ListBoxEffects" SelectionMode="Single" ItemsSource="{StaticResource effects}" SelectionChanged="ListBox_SelectionChanged"
toolkit:TiltEffect.IsTiltEnabled="True"
ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Auto">
<ListBox.Resources>
<vm:EffectItems x:Key="effects"/>
</ListBox.Resources>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" ItemWidth="152" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="14,0,0,10" >
<Image Source="{Binding Thumbnail}" Width="128" Height="128" />
<TextBlock Text="{Binding Name}" FontSize="{StaticResource PhoneFontSizeNormal}" VerticalAlignment="Center" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ViewModel class
public class EffectItems : ObservableCollection<EffectItem>
{
public EffectItems()
{
Add(new EffectItem(new BlackWhiteEffect(), "data/icons/BlackWhite.png"));
Add(new EffectItem(new SepiaEffect(), "data/icons/Sepia.png"));
Add(new EffectItem(new TiltShiftEffect { UpperFallOff = 0.2f, LowerFallOff = 1.0f }, "data/icons/TiltShift.png"));
Add(new EffectItem(new PolaroidEffect { Tinting = 0.8f }, "data/icons/PolaYellow.png", "Pola"));
}
}
At the top of my page I have xmlns:vm="clr-namespace:AppName.ViewModels" which contains no errors.
You can bind your ViewModel to a View by setting the views DataContext. The straight forward way is to set it in the constructor of the code behind:
// Constructor
public MainPage()
{
InitializeComponent();
DataContext = new EffectItems();
}
Then you can set the ItemsSource of your List to the DataContext by using the default binding:
ItemsSource="{Binding}"

how to get listbox selected item value passing to another page for windows phone 7?

Hi am using xaml file given below.I want to get selected item value to details view.
<StackPanel Width="Auto">
<StackPanel VerticalAlignment="Top" Width="Auto">
<ListBox ItemsSource="{Binding Images}" Width="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" SelectionChanged="NotchsList11_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
</StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="White" Margin="0,0,8,0" BorderThickness="1">
<Image Source="{Binding}" Width="152" Height="90" Stretch="Fill" VerticalAlignment="Top"></Image>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Disabled" Width="Auto">
<ListBox ItemsSource="{Binding Titles}" ScrollViewer.VerticalScrollBarVisibility="Disabled" SelectionChanged="NotchsList11_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal">
</StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate >
<Border BorderBrush="White" Margin="0,0,8,0"
BorderThickness="1">
<TextBlock Text="{Binding}" Width="152" Height="80" Padding="5,10,0,0" TextWrapping="Wrap"></TextBlock>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</StackPanel>
My Main.Cs Code
private void NotchsList11_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
NavigationService.Navigate(new Uri("/Test.xaml?parameter={0}",UriKind.Relative));
//NavigationService.Navigate(new Uri("/Page1.xaml?parameter=test", UriKind.Relative));
}
}
I used this thing i cant go to other page with selected item.
i want output like given below image
The simple and efficient approach - have a ViewModel. When the item is selected (hook the SelectionChanged event handler), pass the instance to the ViewModel and navigate to the second page that will show the item details. Make sure that the page is bound to the ViewModel and simply read from the item you passed in.

full-sized image in popup

I'm using ListBox with custom DataTemplate, in this DataTemplate I have two thumbnails, when user clicks on one of this images I need to display a popup with a full-sized image(something like lightbox in JavaScript). I tried to use the Popup control in the DataTemplate, but the popup is positioned to current element on ListBox, not centered in the screen, and I'm not able to make it modal. I also tried to use the Coding4Fun toolkit, but I can't find any documentation or do it without any help.
Here is code of listbox:
<ListBox MaxHeight="600" ItemsSource="{Binding Items}" x:Name="LooksList" u:ScrollViewerMonitor.AtEndCommand="{Binding FetchMoreDataCommand}" d:LayoutOverrides="GridBox" BorderThickness="0" Margin="0,0,0,62">
<ListBox.ItemTemplate>
<DataTemplate>
<views:LookListItem />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And views:LookListItem:
<Grid x:Name="LayoutRoot">
<StackPanel x:Name="MainPanel" Margin="0,53,0,0" Orientation="Horizontal">
<StackPanel x:Name="PhotosPanel" Margin="20,11,0,0" Width="198" Height="126" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Border BorderThickness="3" BorderBrush="White" Margin="0" HorizontalAlignment="Left" Width="93" Height="126">
<Image Source="{Binding Photo1.Thumb}" VerticalAlignment="Center" Tap="Image_Tap" />
</Border>
<Border BorderThickness="3" BorderBrush="White" Margin="12,0,0,0" HorizontalAlignment="Right" Width="93" Height="126">
<Image Source="{Binding Photo2.Thumb}" VerticalAlignment="Center" />
</Border>
</StackPanel>
</StackPanel>
</Grid>
Photo1 and Photo2 should be clickable and after click it should be a popup.
Thanks in advance!
There are a few ways you can go about doing this. I'll show how you can do this with a little code behind.
In your xaml:
<Grid>
<ListBox ItemsSource="{Binding MyItems}" ItemTemplate="{Binding MyTemplate}"
SelectionChanged="ListBox_SelectionChanged"/>
<Popup x:Name="Popup">
<Grid>
<ToggleButton Content="X"
IsChecked="{Binding IsOpen, ElementName=Popup, Mode=TwoWay}"
HorizontalAlignment="Right" VerticalAlignment="Top"/>
<Image x:Name="PopupImage"/>
</Grid>
</Popup>
</Grid>
In your code behind:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs args)
{
ListBox listBox = (ListBox)sender;
MyImageObject obj = (MyImageObject)listBox.SelectedItem;
ImagePopup.Source = MyImageObjct.LargeImageSource;
Popup.IsOpen = true;
// Unselect item so user can "reselect" it -- If you need item later, save it somewhere
listBox.SelectedItem = null;
}
// Handle the back key button to close the popup
protected override void OnBackKeyPress(CancelEventArgs e)
{
if(Popup.IsOpen)
{
Popup.IsOpen = false;
e.Cancel = true;
}
}
UPDATE BASED ON LATEST INFO
If you do not need your view in a separate UserControl (no logic, only placement of controls) you can still use the example, but instead of listening to the SelectionChanged event, listen to the Tap event of each Image.
<ListBox MaxHeight="600" ItemsSource="{Binding Items}" x:Name="LooksList"
BorderThickness="0" Margin="0,0,0,62">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="MainPanel" Margin="0,53,0,0" Orientation="Horizontal">
<StackPanel x:Name="PhotosPanel" Margin="20,11,0,0" Width="198" Height="126" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Border BorderThickness="3" BorderBrush="White" Margin="0" HorizontalAlignment="Left" Width="93" Height="126">
<Image Source="{Binding Photo1.Thumb}" VerticalAlignment="Center" Tap="Image1_Tap" />
</Border>
<Border BorderThickness="3" BorderBrush="White" Margin="12,0,0,0" HorizontalAlignment="Right" Width="93" Height="126">
<Image Source="{Binding Photo2.Thumb}" VerticalAlignment="Center"
Tap="Image2_Tap" />
</Border>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
The event of for Tap events would look something like
private void Image1_Tap(object sender, GestureEventArgs gestureEventArgs)
{
MyImageObject obj = ((FrameworkElement)sender).DataContext as MyImageObject;
// This is the event for Image1 Thumb, so show the Image1 Large
ShowPopup(obj.Photo1.Large);
}
If you do need a separate UserControl
You could create an "ImageOverlay" view much like in my Custom MessageBox Post. In your LookListItem view subscribe to the tap event for both thumbs
<Grid x:Name="LayoutRoot">
<StackPanel x:Name="MainPanel" Margin="0,53,0,0" Orientation="Horizontal">
<StackPanel x:Name="PhotosPanel" Margin="20,11,0,0" Width="198" Height="126" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Border BorderThickness="3" BorderBrush="White" Margin="0" HorizontalAlignment="Left" Width="93" Height="126">
<Image Source="{Binding Photo1.Thumb}" VerticalAlignment="Center" Tap="Thumb1_Tap" />
</Border>
<Border BorderThickness="3" BorderBrush="White" Margin="12,0,0,0" HorizontalAlignment="Right" Width="93" Height="126">
<Image Source="{Binding Photo2.Thumb}" VerticalAlignment="Center" Tap="Thumb2_Tap" />
</Border>
</StackPanel>
</StackPanel>
In the tap events show the ImageOverlay control
private void Thumb1_Tap(object sender, GestureEventArgs gestureEventArgs)
{
ShowOverlay(Photo1.Large);
}
private void Thumb2_Tap(object sender, GestureEventArgs gestureEventArgs)
{
ShowOverlay(Photo2.Large);
}
private void ShowOverlay(ImageSource source)
{
ImageOverlay overlay = new ImageOverlay();
overlay.ImageSource = source;
overlay.Show();
}

Binding Artist from ArtistCollection to PanoramaItem.Listbox on Windows Phone 7

How can I bind all the artists from the Artists collection to a ListBox in a PanoramaItem?
My xaml is as follows:
<controls:PanoramaItem Header="Artist" Name="Pan3">
<!--Double line list with image placeholder and text wrapping-->
<ListBox Name="artistLb" Margin="0,0,-12,0" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
<!--Replace rectangle with image-->
<Rectangle Height="100" Width="100" Fill="#FFE5001b" Margin="12,0,9,0"/>
<StackPanel Width="311">
<TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PanoramaItem>
and xaml.cs code:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
MediaLibrary library = new MediaLibrary();
int CountArtist = library.Artists.Count;
//binding the library.Artist to the Panorama item
}
Thanks!
In my answer I will assume you started from a Windows Phone Panorama Project and already added the reference to Microsoft.Xna.Framework to gain access to the media library.
When binding Ui object like the ListBox to code behind the best solution is to stick with the ViewModel approach that is already provided in the project. In your project you should find a MainViewModel. To this viewmodel add the following property:
private MediaLibrary _library;
public MediaLibrary Library
{
get
{
if (_library == null)
{
_library = new MediaLibrary();
}
return _library;
}
}
This property exposes the MediaLibrary to your xaml. The library is instantiated when called for the first time.
From your xaml it is now possible to bind to this property, I am only showing the ListBox.
<ListBox Margin="0,0,-12,0" ItemsSource="{Binding Library.Artists}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432" Height="78">
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Notice that I am binding the ListBox to the subproperty Artists of the Library property we just created in the viewmodel. I edited the ItemTemplate to show just one TextBlock that binds to the Artist name.
On your emulator you will just see 1 artist as an example, to test this solution with a real device you will have to use the WPConnect tool, which is explained here
I hope this gets you going for now, please let me know if any questions remain.
Have you tried?
artistLb.DataContext = library.Artists;

WP7 image binding

I have a Windows phone 7 application which contains a listbox. I want, for each item in the listbox to have a particular image.
<ListBox Height="606" HorizontalAlignment="Left" ScrollViewer.VerticalScrollBarVisibility="Visible"
Margin="20,20,0,0"
Name="listBox1" VerticalAlignment="Top" Width="414" ItemsSource="{Binding SubList, Mode=OneWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Height="50" Width="50"
VerticalAlignment="Top" Margin="0,10,8,0" Source="{Binding Image, Mode = OneWay}"/>
<StackPanel Orientation="Vertical">
<HyperlinkButton Content="{Binding Cathegory, Mode=OneWay}" NavigateUri="" HorizontalAlignment="Right">
</HyperlinkButton>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And the property binded to the Source property of the Image control is an Uri.
My problem is that the image is not shown in the listbox.
I have tried using a string instead of the Uri but I get the same issue.
I kindly appreciate any help :).
This should work:
public class Item
{
public int Number { get; set; }
public Uri ImageUri { get; set; }
public Item(int number, Uri imageUri)
{
Number = number;
ImageUri = imageUri;
}
}
And the datatemplate:
<ListBox x:Name="Items">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number}"></TextBlock>
<Image Source="{Binding ImageUri}"></Image>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Check out this other SO answer, I believe it contains the answer to your question:
Image UriSource and Data Binding
But the basics of it is that you need to convert your URI/string to a BitmapImage (either via viewmodel property, or converter)

Resources