How to Reference the ViewModel in the View - windows-phone-7

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}"

Related

Access control in stack panel of listbox

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.

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.

Binding in Nested List Boxes to multiple classes

I'm making a nested listed box , basically because I need to bind multiple classes in a single list box , which I'm not able to do and hence the nested listed box.
Here's what I do in the XAML page :
<ListBox Name="abcd" Margin="10,0,30,0" ItemsSource="{Binding Title}" SelectionChanged="ListBox_SelectionChanged" Height="486" Width="404" FontSize="20">
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Margin="0,0,10,0" Width="380" Height="140">
<Grid >
<TextBlock Text="{Binding cdata}" TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeLarge}" />
<ListBox Name="ab" ItemsSource="{Binding Description}" FontSize="14">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Width="380" Height="100">
<Grid>
<TextBlock Text="{Binding cdata}" TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeLarge}" />
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
where ListBox "abcd" has to be bound with class title and "ab" to the class Description.Both the classes have just one string field , "cdata".
In the xaml.cs I do :
abcd.ItemsSource=from article in root.openfooty.news.article
select new Classes.Title
{
cdata = article.title.cdata
};
ab.ItemSource = from article in root.openfooty.news.article
select new Classes.Description
{
cdata = article.description.cdata
};
binding with "abcd" works fine but with "ab" it says "the nam ab doesnt exist in the current context"
Any help would be much appreciated. Thanks :D
Why don't you write a single class like this
public class TitleDescription
{
public string title { get; set; }
public string description { get; set; }
}
and try the databinding ?
abcd.ItemsSource=from article in root.openfooty.news.article
select new Classes.TitleDescription
{
title = article.title.cdata,
description = article.description.cdata
};
And have only one list box like this
<ListBox Name="abcd" Margin="10,0,30,0" SelectionChanged="ListBox_SelectionChanged" Height="486" Width="404" FontSize="20">
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Margin="0,0,10,0" Width="380" Height="140">
<Grid >
<TextBlock Text="{Binding description}" TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeLarge}" />
<TextBlock Text="{Binding title}" TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeLarge}" />
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

How to use Listbox in wp7?

I have one listbox control in my xaml par.My code for listbox is
<ScrollViewer Grid.Row="2" Name="ScrollGrid" VerticalScrollBarVisibility="Auto" VerticalAlignment="Top" Height="Auto" Width="450" Margin="0,100,0,0" >
<ListBox x:Name="TransactionList" Grid.Row="2" HorizontalAlignment="Center" Margin="0,0,0,0" Width="400" Height="Auto">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="0,-10,0,0" Height="120" Width="400" MouseLeftButtonUp="StackPanel_MouseLeftButtonUp">
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Height="80" Width="300" Margin="0,0,20,0">
<TextBlock Height="Auto" Margin="20,0,0,0" VerticalAlignment="Center" Text="vodafone vas" FontSize="30" Foreground="Gray" Name="tbCitynameFavorite" />
</StackPanel>
<StackPanel Orientation="Vertical" Height="60" Width="60" Margin="0,0,0,30">
<Image Name="imgfevdlt" Width="50" Height="40" VerticalAlignment="Center" FlowDirection="LeftToRight" Source="/VodafoneAugmentedReality;component/Images/ArrowMoreSmall.png" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Height="10" Width="350" Margin="-360,60,0,0">
<Image Source="/VodafoneAugmentedReality;component/Images/SaperaterLine.png" Width="350" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
When i run application this will not display any data
But when i comment out this two tag than it will run perfectly
<ListBox.ItemTemplate>
<DataTemplate>
Here i have only static value so it will ok but when i have multiple value than it will create problem
So plase help me i can solve this problem?
You will have to set up a class (say ListBoxItem ) which contains all the properties of your DataTemplate members values
And then define a List of ListBoxItem 's and set it as the ItemSource of your ListBox
Example code
public class ListBoxItem
{
public string CityNameFavorite { set; get; }
// Other required properties follows here
}
List<ListBoxItem> listBoxItems = new List<ListBoxItem>();
listBoxItems.Add(new ListBoxItem() { CityNameFavorite = "Vodafone vas" });
//Add as many items you need
TransactionList.ItemsSource = listBoxItems;
This is just an overview of how it can be achieved, improvise based on your needs

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();
}

Resources