I am making a winodws 8 phone application and trying to have a context menu on it from the Windows Phone tool kit.
I been following this tutorial but instead of list box I am using a long list selector that is built into WP8
<DataTemplate x:Key="GroceryListItemTemplate">
<StackPanel Grid.Column="1" Grid.Row="1">
<TextBlock x:Name="tbName" TextWrapping="Wrap" Text="{Binding Name}" FontSize="32"/>
<TextBlock x:Name="tbProductInfo" TextWrapping="Wrap" Text="{Binding ProductInfoLabel}" HorizontalAlignment="Left"/>
</StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Edit"
Command="{Binding GroceryItemsVm.EditGroceryItemCmd, Source={StaticResource Locator}}"
CommandParameter="{Binding}"/>
<toolkit:MenuItem Header="Delete" Command="{Binding GroceryItemsVm.DeleteGroceryItemCmd, Source={StaticResource Locator}}"
CommandParameter="{Binding}"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</DataTemplate>
above is a stripped down of what my code looks like
here is my list selector
<phone:LongListSelector IsGroupingEnabled="True" ItemsSource="{Binding GroceryItems}" HideEmptyGroups="True" LayoutMode="List" Grid.Row="1">
<phone:LongListSelector.ItemTemplate>
<StaticResource ResourceKey="GroceryListItemTemplate"/>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
Here is my mvvm code I have
public class GroceryItemsVm : ViewModelBase
{
public GroceryItemsVm()
{
if (IsInDesignMode)
{
}
else
{
EditGroceryItemCmd = new RelayCommand<GroceryItem>(this.Edit);
DeleteGroceryItemCmd = new RelayCommand<GroceryItem>(this.Delete);
GroceryItems = // method that gets all items back as grouped.
}
}
private List<Group<GroceryItem>> groceryItems = null;
/// <summary>
/// Sets and gets the GroceryItems property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public List<Group<GroceryItem>> GroceryItems
{
get
{
return groceryItems;
}
set
{
if (groceryItems == value)
{
return;
}
RaisePropertyChanging(() => GroceryItems);
groceryItems = value;
RaisePropertyChanged(() => GroceryItems);
}
}
private async void Delete(GroceryItem obj)
{
// trigged on context delete
}
private void Edit(GroceryItem obj)
{
// triggered on context edit
}
public RelayCommand<GroceryItem> EditGroceryItemCmd
{
get;
private set;
}
public RelayCommand<GroceryItem> DeleteGroceryItemCmd
{
get;
private set;
}
}
public class GroceryItem : ObservableObject
{
/// <summary>
/// The <see cref="Name" /> property's name.
/// </summary>
public const string NamePropertyName = "Name";
private string name = "";
/// <summary>
/// Sets and gets the Name property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public string Name
{
get
{
return name;
}
set
{
if (name == value)
{
return;
}
RaisePropertyChanging(() => Name);
name = value;
RaisePropertyChanged(() => Name);
}
}
}
Now when I run it, It works for the first time, whatever item I choose to edit it, will get the right object for it. However the next object will always be the same. It never changes it choice after the selection is done.
Edit
Here is an example.
The only thing I can think of is override the back button for the pages I am going to and just do a Navigate to the page. It is kinda stupid but that's all I can think off.
public partial class MvvmView1 : PhoneApplicationPage
{
// Constructor
public MvvmView1()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}
protected override void OnBackKeyPress(CancelEventArgs e)
{
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}
}
This is common problem with ContextMenu. I have been trying for some time to think of a solution searching all around for something. You said after you click once it nevers gets it right.
Try the following:
Add the unloaded handler to you contextmenu
as follows:
<DataTemplate x:Key="GroceryListItemTemplate">
<StackPanel Grid.Column="1" Grid.Row="1">
<TextBlock x:Name="tbName" TextWrapping="Wrap" Text="{Binding Name}" FontSize="32"/>
<TextBlock x:Name="tbProductInfo" TextWrapping="Wrap" Text="{Binding ProductInfoLabel}" HorizontalAlignment="Left"/>
</StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu ***Unloaded="ContextMenu_Unloaded"***>
<toolkit:MenuItem Header="Edit"
Command="{Binding GroceryItemsVm.EditGroceryItemCmd, Source={StaticResource Locator}}"
CommandParameter="{Binding}"/>
<toolkit:MenuItem Header="Delete" Command="{Binding GroceryItemsVm.DeleteGroceryItemCmd, Source={StaticResource Locator}}"
CommandParameter="{Binding}"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</DataTemplate>
Remove the * I added them to emphasize the changes. And then the code behind for that handler would be:
private void ContextMenu_Unloaded(object sender, RoutedEventArgs e)
{
var conmen = (sender as ContextMenu);
if (conmen != null)
conmen.ClearValue(DataContextProperty);
}
Let me know if this works.