1

我正在制作一个 winodws 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=file%2c.zip

  1. 运行
  2. 触发上下文菜单以显示超过“1”
  3. 点击编辑 - 注意对话框消息(会说 1)
  4. 点击“返回按钮”
  5. 触发上下文菜单以显示超过“3”
  6. 点击编辑 - 注意对话框消息(会说 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));
        }


    }
4

2 回答 2

1

这是 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);
}

让我知道这个是否奏效。

于 2014-03-20T05:22:52.453 回答
1

根据评论,您有一个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; }
}

因此GroceryItems,您的 LLS 绑定的属性将是

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>
于 2014-03-19T17:52:21.250 回答