2014-09-06 1 views
2

Windows Phone 8.1 용 응용 프로그램을 작성 중이며 listView 항목에 플라이 아웃을 사용하고 싶습니다. 좋은 응용 프로그램을 작성하기 위해 최선을 다하고 있기 때문에 하나의 페이지에서 모든 xaml의 insead 템플릿으로 MVVM 패턴 및 리소스 사전을 사용하려고합니다. 그러나, 내 MenuFlyoutItem 명령을 바인딩 할 수 없습니다 - 페이지의 datacontext가 보이지 않거나 다른 dataContext가있는 것처럼 보입니다.Windows Phone 8.1 - 메뉴 플라이 아웃 항목 클릭 명령 C#

1) 별도의 리소스 사전에 내 템플릿 :

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

내 뷰 모델은 싱글 톤의 정적 종류 : 여기

<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) 그리고이 목록보기는 여기에 몇 가지 코드는 app.xaml.cs

xaml에서 새 VM 인스턴스를 만들려고했지만 작동하지 않았습니다. 어쩌면 내가 잘못한 것일 수도 있습니다.

정말 감사드립니다. 미리 감사드립니다.

안부, 로마

+0

그 그리드는 경우' '당신이 명령 그런 식으로, 즉 당신이 당신의 ViewModel에 넣어 모든 모델에 대한 명령이 필요합니다 의미하는 것이라고 바인딩하고 있습니다. 그래서 "DvdRelease"를 어디에 두 었는지 명령이 있어야합니다. –

+0

고마워, 내가 MVVM 디자인을 깰 수는 있지만 생각해 보겠다. 로직은 viewModel에 있어야하고 모델에는 없다. –

+0

ViewModel에 있다면 더 좋을 것이다. 그런 식으로 구현하려는 경우 여기에서 수행하는 방법에 대한 자습서가 있습니다. http://stackoverflow.com/questions/25613212/how-to-implement-a-navigation-button-in-shared-application -resources/25627927 # 25627927 –

답변

0

@Chubosaurus 소프트웨어 내가이 함께했다 당신의 접근 방식을 다음

내가 그것을 여기에 입력 할 너무 많은 코드 제작이 SO 자습서를 참조 단일 명령을 설정하고 CommandParameter을합니다. 여기

MenuFlyout, 편집을 보여줄 것의 상황에 맞는 메뉴의 종류를 삭제 갖는 TextBlock을 포함하는 DataTemplate 내부에 위치 할 일 항목의 목록에 결합 ListView이다.

MenuFlyoutItem에 뷰 모델의 명령을 결합 할 수있는 키는 ListView 이름을 지정하여 ListView에 이름을 가리 키도록 Command에서 ElementName 속성을 사용하여 바인딩 요소를하는 것입니다. 우리의 뷰 모델의 명령에 액세스하기 위해 우리는 MenuFlyoutItemDataContextItemsSource

의 항목은 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> 
때문에 ListView에의 DataContext을 가서의 명령에 바인딩했습니다

MainPage.xaml.cs는 MainPage의 DataContext가 설정된 곳입니다. ObservableCollection에 종류 및 EditTodo 및 DeleteTodo 명령 인 왜 그렇게 함유

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.

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 구현입니다. 및 DependencyObject에 IAction가 IAction 인터페이스의 실행 방법을 사용하여 MenuFlyout 열기를 구현

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.

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