-->

XAML - MenuFlyoutItem attached to a ListView doesn

2019-03-03 16:45发布

问题:

I develop an Universal app that uses the MVVM-Lght toolkit.

On a page, I show a list of comments. I would like that an user could add a new comment, and edit or delete its existing comments.

For adding new comment, I use an AppBarButton on the CommandBar and it works fine.

For editing and deleting the existing comments, I would like to display a MenuFlyout that offers 2 items: "edit" and "delete". I can display the MenuFlyout but nothing happens when I click on its items...

Here is my concerned xaml code:

    <ListView x:Name="myCommentaires" 
              ItemsSource="{Binding Comments}"
              IsItemClickEnabled="True"
              SelectionMode="Single"
              SelectedItem="{Binding SelectedComment}"
              ContinuumNavigationTransitionInfo.ExitElementContainer="True">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Margin="0,0,19,12"
                            HorizontalAlignment="Stretch">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <!-- 1. Author -->
                        <TextBlock Grid.Column="0"
                                   Text="{Binding name}"
                                   HorizontalAlignment="Stretch" VerticalAlignment="Center"
                                   TextAlignment="Left"
                                   Margin="0" 
                                   Foreground="{StaticResource ThemeBrush}"
                                   Style="{StaticResource ListViewItemSubheaderTextBlockStyle}" />
                        <!-- 2. Date -->
                        <TextBlock Grid.Column="1"
                                   Text="{Binding date, Converter={StaticResource DateToStringConverter}}"
                                   HorizontalAlignment="Stretch" VerticalAlignment="Center"
                                   TextAlignment="Right"
                                   Margin="0" 
                                   Foreground="{StaticResource ThemeBrush}"
                                   Style="{StaticResource ListViewItemSubheaderTextBlockStyle}" />
                    </Grid>
                    <!-- 3. Content -->
                    <TextBlock Text="{Binding content}"
                               TextAlignment="Left"
                               TextWrapping="Wrap"
                               Margin="0" 
                               Foreground="Black"
                               FontSize="20"
                               Style="{StaticResource GroupHeaderTextBlockStyle}" />
                    <!-- MenuFlyout - with Commands -->
                    <FlyoutBase.AttachedFlyout>
                        <MenuFlyout>
                            <MenuFlyout.MenuFlyoutPresenterStyle>
                                <Style TargetType="MenuFlyoutPresenter">
                                    <Setter Property="Background" Value="{StaticResource ThemeBrush}"/>
                                </Style>
                            </MenuFlyout.MenuFlyoutPresenterStyle>
                            <MenuFlyoutItem Text="Edit"
                                            Command="{Binding EditCommentCommand}"/>
                            <MenuFlyoutItem Text="Delete" 
                                            Command="{Binding DeleteCommentCommand}"/>
                        </MenuFlyout>
                    </FlyoutBase.AttachedFlyout>
                    <!-- Behavior -->
                    <i:Interaction.Behaviors>
                        <core:EventTriggerBehavior EventName="Tapped">
                            <local:OpenFlyoutAction />
                        </core:EventTriggerBehavior>
                    </i:Interaction.Behaviors>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>

And its attached code-behind:

    public class OpenFlyoutAction : DependencyObject, IAction
    {
        public object Execute(object sender, object parameter)
        {
            FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender);
            return null;
        }
    }

And this is my ViewModel code:

    // RelaydCommands declarations
    ...
    public RelayCommand AddCommentCommand { get; set; }
    public RelayCommand EditCommentCommand { get; set; }
    public RelayCommand DeleteCommentCommand { get; set; }
    ...

    // RelayCommands are affected in the constructor
    ...
    AddCommentaireCommand = new RelayCommand(AddCommentaire);
    EditCommentaireCommand = new RelayCommand(EditCommentaire);
    DeleteCommentaireCommand = new RelayCommand(DeleteCommentaire);
    ...

    // Methods related to the RelayCommands
    private async void AddComment()
    {
        NavigationService.NavigateTo<EditCommentViewModel>(this, new object[] { _article, _titleStructure.Title }, true); 
    }

    private async void EditComment()
    {
        NavigationService.NavigateTo<EditCommentViewModel>(this, new object[] { _article, _titleStructure.Title, SelectedComment }, true);
    }

    private async void DeleteComment()
    {
        var test = SelectedComment;
    }

I don't meet any problem with the "AddComment" method, which is called from the AppBarButton, but I never enter in the methods "EditComment" and "DeleteComment" whereas I place breakpoints.

I also tried to replace the Command of the MenuFlyoutItem by a CallMethodAction, but it doesn't change anything:

    <!-- MenuFlyout - with CallMethodAction -->
    <FlyoutBase.AttachedFlyout>
        <MenuFlyout>
            <MenuFlyout.MenuFlyoutPresenterStyle>
                <Style TargetType="MenuFlyoutPresenter">
                    <Setter Property="Background" Value="{StaticResource ThemeBrush}"/>
                </Style>
            </MenuFlyout.MenuFlyoutPresenterStyle>
            <MenuFlyoutItem Text="Edit">
                <i:Interaction.Behaviors>
                    <core:EventTriggerBehavior EventName="Click">
                        <core:CallMethodAction MethodName="EditComment" />
                    </core:EventTriggerBehavior>
                </i:Interaction.Behaviors>
            </MenuFlyoutItem>
            <MenuFlyoutItem Text="Delete">
                <i:Interaction.Behaviors>
                    <core:EventTriggerBehavior EventName="Click">
                        <core:CallMethodAction MethodName="DeleteComment" />
                    </core:EventTriggerBehavior>
                </i:Interaction.Behaviors>
            </MenuFlyoutItem>
        </MenuFlyout>
    </FlyoutBase.AttachedFlyout>

=> Could anyone say me what is wrong?

回答1:

You are defining your flyout inside your listview, hence the datacontext is set to the Comments property on your ViewModel. Meaning that the 2 commands you are using are not found!

To fix this, you need to reference your page datacontext and use that to locate the commands.

Give your <Page> a name like x:Name="PageRoot" and change the binding of the commands to

{Binding ElementName=PageRoot, Path=DataContext.EditCommentCommand}