2014-09-06 3 views
2

Я пишу приложение для Windows Phone 8.1, и я хотел использовать всплывающее окно в элементе listView. Поскольку я прилагаю все усилия, чтобы написать хорошее приложение, я пытаюсь использовать шаблоны MVVM и ресурсные словари с шаблонами внутри всех xaml на одной странице. Однако я не могу связать свою команду MenuFlyoutItem - похоже, что он не видит datacontext страницы или имеет некоторый другой dataContext. Вот код:Windows Phone 8.1 - команда меню выпадающего меню C#

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, но это не сработало - возможно, я делал что-то неправильно.

Я бы очень признателен за вашу помощь! Заранее спасибо.

С наилучшими пожеланиями, Роман

+0

Если Энергосистема вашего '' и вы связываете, что команда таким образом, это будет означать, вы будете нуждаться в команде для каждой модели вы положили в вашем ViewModel. Итак, где бы вы ни разместили эту «DvdRelease», также должна быть Command. –

+0

Спасибо, я постараюсь, я думаю, что хотя это ломает дизайн MVVM - логика должна быть в моделях, а не в модели –

+0

Было бы лучше, если бы это было в ViewModel. Если вы хотите реализовать его таким образом, у меня есть хороший учебник о том, как это сделать здесь: http://stackoverflow.com/questions/25613212/how-to-implement-a-navigation-button-in-shared-application -resources/25627927 # 25627927 –

ответ

1

Если придерживаться этого <ItemTemplate> вам придется иметь команду за каждую модель в вашем ViewModel, который не является идеальным.

Чтобы установить единую команду и иметь CommandParameter увидеть эту SO Tutorial я сделал это слишком много кода, чтобы ввести здесь:

Implement a ViewModel Single Command with CommandParamater

0

@Chubosaurus Software следующий свой подход, я придумал это.

Вот ListView привязывается к списку элементов списка задач, помещенного в DataTemplate, который содержит TextBlock, имеющий MenuFlyout показать редактировать, удалять контекстного меню рода вещи.

Ключ, чтобы связать команды в модели представления в MenuFlyoutItem, чтобы дать ListView имя и сделать обязательным использованием ElementName свойства в Command, чтобы указать имя элемента управления ListView элемент. Для получения доступа к командам на наш взгляд, модель, которую мы пройти через управления ListView DataContext и привязать его к команде на него, потому что DataContext из 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 - это то, где установлен DataContext MainPage.

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. 
     } 
    } 
} 

В MainViewModel.cs, содержащие Todos, который является типом 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; } 
    } 
} 

BaseViewModel, который реализует INotifyPropertyChanged.

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, который реализует DependencyObject и IAction, чтобы открыть MenuFlyout с помощью метода Execute на интерфейсе IAction.

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; 
     } 
    } 
} 
Смежные вопросы