Windows Phone 8.1 - 菜单弹出项目单击命令c#

时间:2014-09-06 17:21:37

标签: c# xaml windows-phone-8 mvvm

我正在编写Windows Phone 8.1的应用程序,我想在listView项目上使用flyout。因为我正在尽力编写漂亮的应用程序,所以我试图在一个页面中使用MVVM模式和资源字典以及所有xaml的模板。 但是,我无法绑定我的MenuFlyoutItem命令 - 它似乎没有看到页面的datacontext,或者它有一些其他dataContext。这是一些代码:

1)我的模板在一个单独的资源字典中:

<Grid Margin="0, 0, 0, 10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="4*" />
        </Grid.ColumnDefinitions>

        <Grid.Resources>
            <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
            <converters:EmptyDateConverter x:Key="EmptyDateConverter" />
        </Grid.Resources>

        <i:Interaction.Behaviors>
            <icore:EventTriggerBehavior EventName="Holding">
                <converters:OpenMenuFlyoutAction />
            </icore:EventTriggerBehavior>
        </i:Interaction.Behaviors>

        <FlyoutBase.AttachedFlyout>
            <MenuFlyout>
                <MenuFlyoutItem x:Uid="AddToCalendarMenuItem" Command="{Binding AddToCalendar}" />
            </MenuFlyout>
        </FlyoutBase.AttachedFlyout>

        <Image Grid.Column="0" Source="{Binding ThumbnailUri}"/>
        <StackPanel Grid.Column="1" Orientation="Vertical" Margin="10,0,0,0">
            <TextBlock Text="{Binding Title}" Style="{StaticResource ListItemTitle}"/>
            <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom">
                <TextBlock x:Uid="DvdReleaseDate" />
                <TextBlock Text="{Binding DvdRelease, Converter={StaticResource EmptyDateConverter}}" />
            </StackPanel>
        </StackPanel>
    </Grid>

2)这是列表视图:

<ListView Grid.Row="1" x:Name="SearchListView"
                  ItemsSource="{Binding SearchList}"
                  ItemTemplate="{StaticResource SearchListTemplate}" SelectionChanged="NavigateToMovieDetails"  />

我的ViewModel是app.xaml.cs

中的一种静态单例

我试图在xaml中创建一个新的VM实例,但它没有用 - 也许我做错了。

我真的很感谢你的帮助!提前谢谢。

祝你好运, 罗马

2 个答案:

答案 0 :(得分:1)

如果您坚持使用<ItemTemplate>,则必须在ViewModel中为每个模型设置一个Command,这是不理想的。

要设置一个Command并拥有一个CommandParameter,请参阅此SO教程,我在此处输入了太多代码:

Implement a ViewModel Single Command with CommandParamater

答案 1 :(得分:0)

@Chubosaurus软件按照你的方法我提出了这个。

以下ListView绑定到DataTemplate内放置的待办事项列表,其中包含TextBlock MenuFlyout以显示编辑,删除上下文菜单类型的事情。

将视图模型中的命令绑定到MenuFlyoutItem的关键是使用ListView中的ElementName属性为Command命名并执行元素绑定指向ListView的名称。要访问我们的视图模型中的命令,我们必须通过ListView的DataContext并将其绑定到其上的命令,因为DataContext的{​​{1}}是MenuFlyoutItem ItemsSource

中的项目

MainPage.xaml

<Page
    x:Class="UWA.MenuFlyout.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWA.MenuFlyout"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="using:UWA.MenuFlyout.ViewModels"
    xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
    xmlns:core="using:Microsoft.Xaml.Interactions.Core"
    xmlns:common="using:UWA.MenuFlyout.Core"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid Margin="24,24">
        <ListView x:Name="Todos" ItemsSource="{Binding Todos}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Action}">
                        <FlyoutBase.AttachedFlyout>
                            <MenuFlyout>
                                <MenuFlyoutItem Text="edit" 
                                                Command="{Binding ElementName=Todos, Path=DataContext.EditTodo}"
                                                CommandParameter="{Binding}"/>
                                <MenuFlyoutItem Text="delete" 
                                                Command="{Binding ElementName=Todos, Path=DataContext.DeleteTodo}"
                                                CommandParameter="{Binding}"/>
                            </MenuFlyout>
                        </FlyoutBase.AttachedFlyout>

                        <interactivity:Interaction.Behaviors>
                            <core:EventTriggerBehavior EventName="Holding">
                                <common:OpenMenuFlyoutAction/>
                            </core:EventTriggerBehavior>
                            <core:EventTriggerBehavior EventName="RightTapped">
                                <common:OpenMenuFlyoutAction/>
                            </core:EventTriggerBehavior>
                        </interactivity:Interaction.Behaviors>
                    </TextBlock>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

MainPage.xaml.cs是设置MainPage的DataContext的地方。

namespace UWA.MenuFlyout
{
    using UWA.MenuFlyout.ViewModels;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Navigation;

    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            this.NavigationCacheMode = NavigationCacheMode.Required;
            this.DataContext = new MainViewModel();
        }

        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.
        /// This parameter is typically used to configure the page.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // TODO: Prepare page for display here.

            // TODO: If your application contains multiple pages, ensure that you are
            // handling the hardware Back button by registering for the
            // Windows.Phone.UI.Input.HardwareButtons.BackPressed event.
            // If you are using the NavigationHelper provided by some templates,
            // this event is handled for you.
        }
    }
}

包含Todos的MainViewModel.cs,它是ObservableCollection类型以及EditTodo和DeleteTodo命令。

namespace UWA.MenuFlyout.ViewModels
{
    using System.Collections.ObjectModel;
    using System.Windows.Input;
    using UWA.MenuFlyout.Core;
    using UWA.MenuFlyout.Models;

    public class MainViewModel : BaseViewModel
    {
        private ICommand editTodo;

        private ICommand deleteTodo;

        public MainViewModel()
        {
            this.Todos = new ObservableCollection<TodoModel>
            {
                new TodoModel { Id = 1, Action = "Buy Milk", IsDone = true },
                new TodoModel { Id = 2, Action = "Buy Groceries", IsDone = false }
            };
        }

        public ObservableCollection<TodoModel> Todos { get; set; }

        public ICommand EditTodo
        {
            get
            {
                if (this.editTodo == null)
                {
                    this.editTodo = new RelayCommand(this.OnEditTodo);
                }

                return this.editTodo;
            }
        }

        public ICommand DeleteTodo
        {
            get
            {
                if (this.deleteTodo == null)
                {
                    this.deleteTodo = new RelayCommand(this.OnDeleteTodo);
                }

                return this.deleteTodo;
            }
        }

        public void OnEditTodo(object parameter)
        {
            // perform edit here
            var todo = parameter as TodoModel;
        }

        public void OnDeleteTodo(object parameter)
        {
            // perform delete here
            var todo = parameter as TodoModel;
        }
    }
}

模特

namespace UWA.MenuFlyout.Models
{
    public class TodoModel
    {
        public int Id { get; set; }

        public string Action { get; set; }

        public bool IsDone { get; set; }
    }
}

实现INotifyPropertyChanged。

的BaseViewModel
namespace UWA.MenuFlyout.Core
{
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

一个简单的ICommand实现。

namespace UWA.MenuFlyout.Core
{
    using System;
    using System.Windows.Input;

    public class RelayCommand : ICommand
    {
        private Action<object> action;

        public RelayCommand(Action<object> action)
        {
            this.action = action;
        }

        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            this.action(parameter);
        }
    }
}

OpenMenuFlyoutAction,它使用IAction接口上的Execute方法实现DependencyObject和IAction以打开MenuFlyout。

namespace UWA.MenuFlyout.Core
{
    using Microsoft.Xaml.Interactivity;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls.Primitives;

    public class OpenMenuFlyoutAction : DependencyObject, IAction
    {
        public object Execute(object sender, object parameter)
        {
            var frameworkElement = sender as FrameworkElement;
            var flyoutBase = FlyoutBase.GetAttachedFlyout(frameworkElement);
            flyoutBase.ShowAt(frameworkElement);

            return null;
        }
    }
}