上下文菜单不断得到错误的对象使用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"
  2. 点击编辑-注释对话框消息(将显示1)
  3. 点击"返回键"
  4. 触发上下文菜单显示超过"3"
  5. 点击编辑-注释对话框消息(将显示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));
        }

    }

上下文菜单不断得到错误的对象使用Mvvm

这是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>