this.DataContext is NULL? Use to be filled - Switched to Autofac - windows-phone-7

I am using MVVM Light, Autofac for windows phone 7 and Autofac locator.
With autofac
http://www.nuget.org/packages/Autofac.Wp7
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
using MvvmLight1.Model;
using Autofac;
namespace MvvmLight1.ViewModel
{
public class ViewModelLocator
{
static ViewModelLocator()
{
var builder = new ContainerBuilder();
builder.RegisterType<MainViewModel>();
var container = builder.Build();
ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(container));
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
}
}
using Microsoft.Phone.Controls;
namespace MvvmLight1
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
var main = this.DataContext as MainPage; // will be null
}
}
}
<phone:PhoneApplicationPage x:Class="MvvmLight1.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:ignore="http://www.ignore.com"
mc:Ignorable="d ignore"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait"
Orientation="Portrait"
d:DesignWidth="480"
d:DesignHeight="768"
shell:SystemTray.IsVisible="True"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<!--LayoutRoot contains the root grid where all other page content is placed-->
<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 x:Name="TitlePanel"
Grid.Row="0"
Margin="24,24,0,12">
<TextBlock x:Name="ApplicationTitle"
Text="{Binding ApplicationTitle}"
Style="{StaticResource PhoneTextNormalStyle}" />
<TextBlock x:Name="PageTitle"
Text="{Binding PageName}"
Margin="-3,-8,0,0"
Style="{StaticResource PhoneTextTitle1Style}" />
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentGrid"
Grid.Row="1">
<TextBlock Text="{Binding WelcomeTitle}"
Style="{StaticResource PhoneTextNormalStyle}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="40"
TextWrapping="Wrap"
TextAlignment="Center" />
</Grid>
</Grid>
</phone:PhoneApplicationPage>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Autofac;
using Microsoft.Practices.ServiceLocation;
namespace MvvmLight1
{
public sealed class AutofacServiceLocator : ServiceLocatorImplBase
{
readonly IComponentContext _container;
public AutofacServiceLocator(IComponentContext container)
{
if (container == null)
throw new ArgumentNullException("container");
_container = container;
}
protected override object DoGetInstance(Type serviceType, string key)
{
return key != null ? _container.ResolveNamed(key, serviceType) : _container.Resolve(serviceType);
}
protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
{
var enumerableType = typeof(IEnumerable<>).MakeGenericType(serviceType);
object instance = _container.Resolve(enumerableType);
return ((IEnumerable)instance).Cast<object>();
}
}
}
using GalaSoft.MvvmLight;
using MvvmLight1.Model;
namespace MvvmLight1.ViewModel
{
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
}
}
}
now the viewModel in my constructor of MainPage.cs will always be null.
When I just used SimpleIoc it was filled with the Main Object.

Related

Deserializing a JSON array to LongListSelector Windows Phone 8

How can i deserialize this jsonx variable and put it on a longlistselector on windows phone?
Currently i can only echo one string with messagebox. i need key-value sets on a longlistselector.
edit: this is my answer http://pastebin.com/CcADHaab
here is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using PhoneApp5.Resources;
using Newtonsoft.Json;
namespace PhoneApp5
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
string json = #"{
'Email': 'james#example.com',
'Active': true,
'CreatedDate': '2013-01-20T00:00:00Z'
}";
string jsonx = #"{
'Table1': [
{
'id': 0,
'item': 'item 0'
},
{
'id': 1,
'item': 'item 1'
}
]
}";
Account account = JsonConvert.DeserializeObject<Account>(json);
// Console.WriteLine(account.Email);
// james#example.com
MessageBox.Show(account.Email);
list.ItemsSource = new BookList();
}
}
public class BookList : List<Account>
{
public BookList()
{
}
}
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
// public IList<string> Roles { get; set; }
}
///////////////////////////
}
and my XAML
<phone:PhoneApplicationPage
x:Class="PhoneApp5.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"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
<TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:LongListSelector Name="list">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding id}" />
<TextBlock Text=" ( " />
<TextBlock Text="{Binding item}" FontStyle="Italic" />
<TextBlock Text=" )" />
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
You need a class to represent your json:
public class MyClass
{
public string Id { get; set; }
public string Item { get; set; }
}
Set a ObservableCollection property in your Form:
public ObservableCollection<MyClass> MyClassCollection { get; set; }
and then set the MyClassCollection property to your Deserialized json
MyClassCollection = JsonConvert.DeserializeObject<ObservableCollection<MyClass>>(e.Result);
That way you're binding your class list to the LongListSelector Control in your XAML:
<phone:LongListSelector Name="list" ItemsSource="{Binding MyClassCollection}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding id}" />
<TextBlock Text=" ( " />
<TextBlock Text="{Binding item}" FontStyle="Italic" />
<TextBlock Text=" )" />
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
That should work.

Build an UI like option menu

I think the question says it all: I want to build an Windows 8 Store app but how can I build an UI like this:
I think left is a normal ListView. The important thing is that I want an own AppBar for each ListViewEntry. And how can I load different pages (with different AppBars) in the right content area?
You can put a ContentControl in the main panel and another one in the AppBar, then bind their Content properties to the SelectedItem property of the ListBox on the left and use ContentTemplateSelector to display the right UI for the selected page.
*EDIT - Sample
XAML
<Page
x:Class="App17.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App17"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<local:PropertyPageTemplateSelector
x:Key="PropertyPageTemplateSelector"/>
</Page.Resources>
<Grid
Background="LemonChiffon">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition
Width="2*" />
</Grid.ColumnDefinitions>
<ListBox
x:Name="listBox"
DisplayMemberPath="Label"/>
<ContentControl
Grid.Column="1"
Content="{Binding SelectedItem, ElementName=listBox}"
ContentTemplateSelector="{StaticResource PropertyPageTemplateSelector}">
<ContentControl.Resources>
<DataTemplate
x:Key="Options">
<StackPanel>
<TextBlock
Text="{Binding Label}"
FontSize="32"
Foreground="SlateGray" />
<Rectangle
Width="400"
Height="400"
Fill="Aquamarine" />
</StackPanel>
</DataTemplate>
<DataTemplate
x:Key="Preferences">
<StackPanel>
<TextBlock
Text="{Binding Label}"
FontSize="32"
Foreground="SlateGray" />
<Rectangle
Width="400"
Height="400"
Fill="Khaki" />
</StackPanel>
</DataTemplate>
<DataTemplate
x:Key="Properties">
<StackPanel>
<TextBlock
Text="{Binding Label}"
FontSize="32"
Foreground="SlateGray" />
<Rectangle
Width="400"
Height="400"
Fill="LawnGreen" />
</StackPanel>
</DataTemplate>
<DataTemplate
x:Key="Settings">
<StackPanel>
<TextBlock
Text="{Binding Label}"
FontSize="32"
Foreground="SlateGray" />
<Rectangle
Width="400"
Height="400"
Fill="Violet" />
</StackPanel>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</Grid>
</Page>
C#
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace App17
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
listBox.ItemsSource =
new List<PropertyPageViewModel>(
new PropertyPageViewModel[]
{
new OptionsPropertyPageViewModel(),
new PreferencesPropertyPageViewModel(),
new PropertiesPropertyPageViewModel(),
new SettingsPropertyPageViewModel(),
});
}
}
public abstract class PropertyPageViewModel
{
public abstract string Label { get; }
}
public class OptionsPropertyPageViewModel : PropertyPageViewModel
{
public override string Label { get { return "Options"; } }
}
public class PreferencesPropertyPageViewModel : PropertyPageViewModel
{
public override string Label { get { return "Preferences"; } }
}
public class PropertiesPropertyPageViewModel : PropertyPageViewModel
{
public override string Label { get { return "Properties"; } }
}
public class SettingsPropertyPageViewModel : PropertyPageViewModel
{
public override string Label { get { return "Settings"; } }
}
public class PropertyPageTemplateSelector : DataTemplateSelector
{
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
if (item == null) return base.SelectTemplateCore(item, container);
var contentControl = (ContentControl)container;
var viewModel = (PropertyPageViewModel)item;
var templateKey = viewModel.Label;
return (DataTemplate)contentControl.Resources[templateKey];
}
}
}

How can I get control in DataTemplate?

So, I have a code:
<tool:LongListSelector x:Name="citiesListGropus" Background="Transparent"
ItemTemplate="{StaticResource citiesItemTemplate}"
GroupHeaderTemplate="{StaticResource groupHeaderTemplate}"
GroupItemTemplate="{StaticResource groupItemTemplate}" Height="468" Margin="0,68,0,0">
<tool:LongListSelector.GroupItemsPanel>
<ItemsPanelTemplate>
<tool:WrapPanel/>
</ItemsPanelTemplate>
</tool:LongListSelector.GroupItemsPanel>
</tool:LongListSelector>
And have a DataTemplate:
<DataTemplate x:Key="groupHeaderTemplate" x:Name="groupHeaderTemplateName">
<Border Background="{StaticResource PhoneAccentBrush}" Width="75" Height="75" Margin="-333, 15, 0, 15" x:Name="groupHeaderName">
<TextBlock Text="{Binding Title}" FontSize="40" Foreground="White" Margin="15, 15, 0, 0"/>
</Border>
</DataTemplate>
How can I change a property Visibility of Border in DataTemplate ? I want to hide DataTemplate. But I can't bind my data to a property such as TextBlock Text="{Binding Title}", because I make binding data once, then I need to change some properties after data binding.
Any Ideas?
UPDATE 1
So, my main goal is filter the list of cities. I want to filter them by name.
My algorithm:
1) I get data from WebService.
2) Load my ViewModel
if (!App.CitiesViewModel.IsDataLoaded)
{
App.CitiesViewModel.LoadData(serviceResponse.Result);
}
3) Group the cities by name. My code like this code.
This is important, especially for LongListSeletstor I have to use templates.
Ok, my data ready. Now I do not need a web service.
<!-- The template for city items -->
<DataTemplate x:Key="citiesItemTemplate">
<StackPanel Name="PlacePanel"
Orientation="Horizontal" Margin="0,0,0,17"
Tag="{Binding Id}" Visibility="{Binding IsVisibility}">
<Image Height="75" Width="75" HorizontalAlignment="Left" Margin="12,0,9,0" Name="Image" Stretch="Fill" VerticalAlignment="Top" Source="{Binding Image}"/>
<StackPanel Width="311">
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
I have TextBox, when I type name of a city - unnecessary cities hide. I can use data binding and INotifyPropertyChanged, so I can hide cities.
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox name = (TextBox)sender;
foreach(var place in App.CitiesViewModel.Items
.Where(city => (city.Name.Contains(name.Text)) && (city.IsShow == true)))
{
city.IsVisibility = Visibility.Visible;
}
foreach (var city in App.CitiesViewModel.Items
.Where(city => !city.Name.Contains(name.Text)))
{
city.IsVisibility = Visibility.Collapsed;
}
}
But I have some problems, I can't hide this DataTemplate when I search cities:
<DataTemplate x:Key="groupHeaderTemplate" x:Name="groupHeaderTemplateName">
<Border Background="{StaticResource PhoneAccentBrush}" Width="75" Height="75" Margin="-333, 15, 0, 15" x:Name="groupHeaderName">
<TextBlock Text="{Binding Title}" FontSize="40" Foreground="White" Margin="15, 15, 0, 0"/>
</Border>
</DataTemplate>
When I type name of a cities I want hide GroupHeaderTemplate. When TextBox lost focus show GroupHeaderTemplate.
I borrowed this picture here.
Update 2
My mistake was that I did not use PropertyChangedEventHandler. After adding this to GroupCity property and implementing an interface INotifyPropertyChanged I can change property Data Template after data binding.
private IList<Group<City>> citiesCollectionGroup;
var cityByName = from city in App.ViewModel.Items
group city by Convert.ToString(City.Name[0]).ToLower()
into c orderby c.Key select new
GroupCity<CitiesViewModel>(Convert.ToString(c.Key[0]).ToLower(), c);
citiesCollectionGroup = cityByName.ToList();
this.citiesListGropus.ItemsSource = citiesCollectionGroup;
public class GroupCity<T> : IEnumerable<T>, INotifyPropertyChanged
{
public GroupCity(string name, IEnumerable<T> items)
{
this.Title = name;
this.IsVisibility = Visibility.Visible;
this.Items = new List<T>(items);
}
public override bool Equals(object obj)
{
GroupCity<T> that = obj as GroupCity<T>;
return (that != null) && (this.Title.Equals(that.Title));
}
public string Title
{
get;
set;
}
private Visibility _isVisibility;
public Visibility IsVisibility
{
get
{
return _isVisibility;
}
set
{
_isVisibility = value;
NotifyPropertyChanged("IsVisibility");
}
}
public IList<T> Items
{
get;
set;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
return this.Items.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.Items.GetEnumerator();
}
#endregion
}
Xaml code:
<DataTemplate x:Key="groupHeaderTemplate" x:Name="groupHeaderTemplateName">
<Border Background="{StaticResource PhoneAccentBrush}" Width="75" Height="75" Margin="-333, 15, 0, 15" x:Name="groupHeaderName" Visibility="{Binding IsVisibility}">
<TextBlock Text="{Binding Title}" FontSize="40" Foreground="White" Margin="15, 15, 0, 0"/>
</Border>
</DataTemplate>
Now we can change Visibility groupHeaderTemplate.
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
foreach (GroupCity<CitiesViewModel> city in citiesCollectionGroup)
{
city.IsVisibility = Visibility.Collapsed;
}
//
}
private void SearchText_LostFocus(object sender, RoutedEventArgs e)
{
foreach (GroupCity<CitiesViewModel> city in citiesCollectionGroup)
{
city.IsVisibility = Visibility.Visible;
}
//
}
You can write your own simple DataTemplateSelector to do this. Check this out for more information.
With "How can I change a property Visibility of Border in DataTemplate ? I want to hide DataTemplate. " I understand that you want to change the visibility of an item based on a property, see example below.
(If the code below isn't quite the solution you are looking for please provide some more information about what you are trying to achieve. Re-reading your question and the comments I got on this example I doubt this is what you want to do, but I don't want to guess so I'm simply answering my interpretation of your question).
With bindings you can:
Bind the visibility property directly to a a property of type Visibility (example with listbox and Person1)
Bind the Visibility property to a boolean property, and use a converter to convert that to the Visibility type (listbox2 and Person2 + BoolToVis class).
There are more ways, but this are the two most simple to implement in my opinion.¨
result of code below:
View:
<phone:PhoneApplicationPage
x:Class="VisibilityWP.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"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
xmlns:VisibilityWP="clr-namespace:VisibilityWP"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.Resources>
<VisibilityWP:BoolToVis x:Key="BooleanToVisibilityConverter" />
</Grid.Resources>
<StackPanel>
<ListBox x:Name="listBox" Height="300">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Width="200" Visibility="{Binding Visibility}" Background="Blue">
<TextBlock Text="{Binding Name}" FontSize="40" Foreground="White" Margin="15, 15, 0, 0"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox x:Name="listBox2" Height="300">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Width="200" Visibility="{Binding ShowBorder, Converter={StaticResource BooleanToVisibilityConverter}}" Background="Red">
<TextBlock Text="{Binding Name}" FontSize="40" Foreground="White" Margin="15, 15, 0, 0"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Grid>
</Grid>
Code behind:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;
namespace VisibilityWP
{
public partial class MainPage
{
public MainPage()
{
InitializeComponent();
DataContext = this;
listBox.ItemsSource = new List<Person1>
{
new Person1 {Name = "Iris", Visibility = Visibility.Visible},
new Person1 {Name = "Somebody", Visibility = Visibility.Collapsed},
new Person1 {Name = "Peter", Visibility = Visibility.Visible},
};
listBox2.ItemsSource = new List<Person2>
{
new Person2 {Name = "Iris", ShowBorder = true},
new Person2 {Name = "Mia", ShowBorder = true},
new Person2 {Name = "Somebody", ShowBorder = false}
};
}
}
public class Person1
{
public string Name { get; set; }
public Visibility Visibility { get; set; }
}
public class Person2
{
public string Name { get; set; }
public bool ShowBorder { get; set; }
}
public sealed class BoolToVis : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (value is bool && (bool)value) ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value is Visibility && (Visibility)value == Visibility.Visible;
}
}
}

Remove an item from listbox in WP7

I am both a freshman in WP7 and c# development .I confused with listbox removing operate. I want to remove a item through a click event(remove item data and refresh UI).I've searched in website,and knew first resource should extend ObservableCollection, but How to do next?Who can give me a more detail example.
Here is my code MainPage.xaml.Example source download
<phone:PhoneApplicationPage x:Class="WPListBoxImage.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:data="clr-namespace:WPListBoxImage"
mc:Ignorable="d"
d:DesignWidth="480"
d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait"
Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<phone:PhoneApplicationPage.Resources>
<data:Products x:Key="productCollection" />
<data:PriceConverter x:Key="priceConvert" />
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<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 x:Name="TitlePanel"
Grid.Row="0"
Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle"
Text="PDSA"
Style="{StaticResource PhoneTextNormalStyle}" />
<TextBlock x:Name="PageTitle"
Text="Products"
Margin="9,-7,0,0"
Style="{StaticResource PhoneTextTitle1Style}" />
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel"
Grid.Row="1"
Margin="12,0,12,0">
<ListBox x:Name="lstData"
ItemsSource="{Binding Source={StaticResource productCollection}, Path=DataCollection}" SelectionChanged="lstData_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Margin="8"
VerticalAlignment="Top"
Source="{Binding Path=ImageUri}"
Width="100"
Height="100" />
<StackPanel>
<TextBlock Margin="8"
Width="250"
TextWrapping="Wrap"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Text="{Binding Path=ProductName}" />
<TextBlock Width="100"
Margin="8,0,8,8"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Text="{Binding Path=Price, Converter={StaticResource priceConvert}}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
namespace WPListBoxImage
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void lstData_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBoxItem lbi = ((sender as ListBox).SelectedItem as ListBoxItem);
//delete a item,what should to do next?
}
}
}
Products.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace WPListBoxImage
{
//a ObservableCollection<T>,
public class Products : ObservableCollection<Product>
{
public Products()
{
DataCollection = new ObservableCollection<Product>();
BuildCollection();
}
private const string IMG_PATH = "../Images/";
public ObservableCollection<Product> DataCollection { get; set; }
public ObservableCollection<Product> BuildCollection()
{
//DataCollection = new ObservableCollection<Product>();
DataCollection.Add(new Product("Haystack Code Generator for .NET", 799, IMG_PATH + "Haystack.jpg"));
DataCollection.Add(new Product("Fundamentals of N-Tier eBook", Convert.ToDecimal(19.95), IMG_PATH + "FundNTier_100.jpg"));
DataCollection.Add(new Product("Fundamentals of ASP.NET Security eBook", Convert.ToDecimal(19.95), IMG_PATH + "FundSecurity_100.jpg"));
DataCollection.Add(new Product("Fundamentals of SQL Server eBook", Convert.ToDecimal(19.95), IMG_PATH + "FundSQL_100.jpg"));
DataCollection.Add(new Product("Fundamentals of VB.NET eBook", Convert.ToDecimal(19.95), IMG_PATH + "FundVBNet_100.jpg"));
DataCollection.Add(new Product("Fundamentals of .NET eBook", Convert.ToDecimal(19.95), IMG_PATH + "FundDotNet_100.jpg"));
DataCollection.Add(new Product("Architecting ASP.NET eBook", Convert.ToDecimal(19.95), IMG_PATH + "ArchASPNET_100.jpg"));
DataCollection.Add(new Product("PDSA .NET Productivity Framework", Convert.ToDecimal(2500), IMG_PATH + "framework.jpg"));
return DataCollection;
}
}
}
Product.cs
using System;
namespace WPListBoxImage
{
public class Product
{
#region Constructors
public Product()
{
}
public Product(string name, decimal price, string imageUri)
{
this.ProductName = name;
this.Price = price;
this.ImageUri = imageUri;
}
#endregion
public string ProductName { get; set; }
public decimal Price { get; set; }
public string ImageUri { get; set; }
}
}
Here is app screenshot.
thank's for your patience.
Your Products class shouldn't inherit anything.
public class Products
Accessing all the items in your collection is done through the DataCollection property of the Product class. For example,
Products myProducts = new Products();
ObservableCollection<Product> myData = myProducts.DataCollection;
It also depends on how you want to use Products. You may be able to totally do away with this class and then do something like:
ObservableCollection<Product> Products = new ObservableCollection<Product>();
Products.Add(new Product("Haystack Code Generator for .NET", 799, IMG_PATH + "Haystack.jpg"));
// etc...
Firstly you need to obtain a reference to your product collection:
Products productCollection = this.Resources["productCollection"] as Products;
Then find the item that was clicked, this will be the DataContext of the ListBoxItem:
ListBoxItem lbi = ((sender as ListBox).SelectedItem as ListBoxItem);
Product product = lbi.DataContext as Product;
(although, I think that as your listbox is databound, the SelectedItem should be a Product instance. You can check this yourself in the debugger)
Then simply remove it, the ObservableCollection will ensure that the UI is updated:
productCollection.Remove(product);

Cannot see the content and image on the user control

I created the user control, I added them in the stackpanel by coding. when it is complier, there is no error. However, I didn't seen any content and image on this user control. When the button is clicked, it open another page. I know the click event is working fine. Would someone show me how to solve the problem? Thanks in advance.
The following is my UserControl.xaml:
<UserControl x:Name="NoButtonListItemControl"
x:Class="PhoneApp1.NobuttonListItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-
compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<Grid x:Name="LayoutRoot" >
<StackPanel Margin="14,17,20,48" >
<Image Source="{Binding Path=PicFileName,
ElementName=NoButtonListItemControl}"
Width="120" Height="120"></Image>
<Button Content="{Binding Path=Description,
ElementName=NoButtonListItemControl }"
ClickMode="Press"
Click="btnNoButtonListItem_Click" FontFamily="Georgia"
FontSize="15" Foreground="SkyBlue" Height="90"
Width="400" />
<TextBlock Text="{Binding Path=ID,
ElementName=NoButtonListItemControl }"
Style="{StaticResource pageTitleStyle}"
TextAlignment="{Binding}" />
</StackPanel>
</Grid>
 
The following is my UserControl.xaml.cs:
namespace PhoneApp1
{
public partial class NobuttonListItem : UserControl
{
public NobuttonListItem()
{
InitializeComponent();
}
public static DependencyProperty PicFileNameProperty =
DependencyProperty.Register("PicFileName", typeof(string),
typeof(NobuttonListItem), null);
public static DependencyProperty DescriptionProperty =
DependencyProperty.Register("Description", typeof(string),
typeof(NobuttonListItem), null);
public static DependencyProperty IDProperty =
DependencyProperty.Register("ID", typeof(string),
typeof(NobuttonListItem), null);
public string PicFileName
{
get
{
return (string)GetValue(PicFileNameProperty);
}
set
{
SetValue(PicFileNameProperty, value);
}
}
public string Description
{
get
{
return (string)GetValue(DescriptionProperty);
}
set
{
SetValue(DescriptionProperty, value);
}
}
public string ID
{
get
{
return (string)GetValue(IDProperty);
}
set
{
SetValue(IDProperty, value);
}
}
private void btnNoButtonListItem_Click(object sender,
RoutedEventArgs e)
{
App.Navigate(new
Uri(String.Format("/CallPage.xaml?ID={0}",ID),
UriKind.Relative));
}
}
}
 
There is test.xaml page in which I added the user control:
<phone:PhoneApplicationPage xmlns:my="clr-
namespace:PhoneApp1"
x:Class="PhoneApp1.test"
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"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0"
Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-
7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<StackPanel x:Name="spListPanel" Loaded="spListPanel_Loaded"
Grid.Row="1" Margin="12,0,12,0">
</StackPanel>
<Grid Grid.Row="2" Margin="12,0,12,0">
<StackPanel>
</StackPanel>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
The code behind of the test.xam l page:
namespace PhoneApp1
{
public partial class test : PhoneApplicationPage
{
public test()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded);
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
ShowList();
}
void ShowList()
{
int userControlUniqueID = 0;
AddItem("1", "Test 1", "onHold_icon.png", 1);
AddItem("2", "Test 2", "responded_icon.png",2);
}
void AddItem(string id, string description, string fileName,
int userControlUniqueID)
{
NobuttonListItem item = new NobuttonListItem();
item.Name = "lst_" + Convert.ToString(userControlUniqueID);
item.ID = id;
item.Description = description;
item.PicFileName = "/images" + "/" +fileName;
spListPanel.Children.Add(item);
}
}
}
Don't forget to add the following code in your "CodeBehind" file
this.DataContext = this;
If it still doesn't work, please post some of the output in the output window

Resources