上下文菜单不断得到错误的对象使用Mvvm
本文关键字:对象 Mvvm 错误 菜单 上下文 | 更新日期: 2023-09-27 17:50:54
我正在制作一个Windows 8手机应用程序,并试图从Windows phone工具包中获得一个上下文菜单。
我一直在遵循本教程,但我使用的不是列表框,而是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>
上面的是我的代码的精简版
这是列表选择器
<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>
这是我的mvvm代码,我有
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);
}
}
}
现在当我运行它时,它第一次工作,无论我选择编辑它的项目,都会得到正确的对象。但是下一个对象总是相同的。在选择完成后,它永远不会改变它的选择。
编辑
下面是一个例子。
https://onedrive.live.com/redir?resid=FAE864D71B4770C6 ! 19080, authkey = ! ACUC2xXmZLVD7fE& ithint =文件% 2 c.zip
- 触发上下文菜单显示超过"1"
- 点击编辑-注释对话框消息(将显示1) 点击"返回键"
- 触发上下文菜单显示超过"3"
- 点击编辑-注释对话框消息(将显示3)
我能想到的唯一的事情是覆盖后退按钮的页面,我要去,只是做一个导航到页面。这是有点愚蠢,但这是所有我能想到的。
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));
}
}
这是ContextMenu的常见问题。一段时间以来,我一直在努力寻找一个解决方案。你说过点击一次后,它就永远不会正确。
尝试以下操作:
将未加载的处理程序添加到您的contextmenu
,如下所示:
<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>
删除*我添加它们是为了强调更改。然后处理程序后面的代码是:
private void ContextMenu_Unloaded(object sender, RoutedEventArgs e)
{
var conmen = (sender as ContextMenu);
if (conmen != null)
conmen.ClearValue(DataContextProperty);
}
根据注释,您有一个GroceryItemsVm
类,看起来像下面这样。
public class GroceryItemVm : INotifyPropertyChanged
{
public string Name { get; set; }
public string ProductInfoLabel{ get; set; }
public ICommand EditGroceryItemCmd { get; private set; }
public ICommand DeleteGroceryItemCmd { get; private set; }
}
那么LLS绑定的GroceryItems
属性就是
public IEnumerable<GroceryItemVm> GroceryItems { get; set;}
如果是这种情况,那么DataTemplate中项目的DataContext是GroceryItemsVm
的实例。DataTemplate中的所有绑定都应该直接绑定到那个实例
<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 EditGroceryItemCmd}"/>
<toolkit:MenuItem Header="Delete" Command="{Binding DeleteGroceryItemCmd}"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</DataTemplate>