web-dev-qa-db-fra.com

Liaison à la propriété tapée d'élément ListView depuis le modèle de vue

J'essaie de lier un événement à un ListView, sur ma page de menu, en utilisant la propriété itemtapped. Actuellement, j'utilise le framework MVVM (Xamarin form labs) dans mon application. Ce que j'essaie d'accomplir, c'est lorsqu'un utilisateur appuie sur l'élément de menu, l'application navigue vers la vue correcte.

Voici le code xaml:

<ListView x:Name="list"
        ItemsSource="{Binding MenuItems}" 
        SelectedItem="{Binding SelectedItem}" 
        ItemTapped= SET-BINDING-HERE >
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <ViewCell.View>
          //setup template here
        </ViewCell.View>
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate> 
</ListView>

Je veux lier l'événement itemtapped à cette fonction:

public void NavigateTo(object sender, ItemTappedEventArgs args)
  {
      var test = args.Item as MenuModel;
      cPageTypes.GetByKey(test.CommandParameter)
                .SwitchRootPage(AIMCore.ViewModels.ElliottBaseViewModel.MasterPage);
      list.SelectedItem = null;
      AIMCore.ViewModels.BaseViewModel.MasterPage.IsPresented = false;
  }

Je peux actuellement faire en sorte que cela fonctionne si j'ajoute la fonction au code de la vue derrière et que je définis ensuite ItemTapped = 'NavigatTo', mais cela semble faux car il défait le concept MVVM. Ce que je veux vraiment faire, c'est lier à l'événement cette même fonctionnalité dans mon ViewModel quelque chose comme ceci:

<ListView x:Name="list"
        ItemsSource="{Binding MenuItems}" 
        SelectedItem="{Binding SelectedItem}" 
        ItemTapped= "{Binding NavigateTo}" > // this binding is to the ViewModel

Cependant cela ne fonctionne pas ou je ne le fais pas correctement. Lorsque j'essaye de l'implémenter de cette façon, le code produit et génère une erreur.

Erreur: Xamarin.Forms.Xaml.XamlParseException: aucune propriété du nom ItemTapped trouvée à Xamarin.Forms.Xaml.BaseValueNode.SetPropertyValue

16
Jared Reeves

J'ai suivi la même architecture et effectué la création d'un contrôle de liste personnalisé et créé 1 propriété pouvant être liée avec une commande que j'ai remplacée dans mon modèle de vue à l'aide du code ci-dessous:

Page de contrôle personnalisé [.cs] dans mon PCL

using System;
using System.Windows.Input;
using Xamarin.Forms;


namespace YourNS {

    public class ListView : Xamarin.Forms.ListView {

        public static BindableProperty ItemClickCommandProperty = BindableProperty.Create<ListView, ICommand>(x => x.ItemClickCommand, null);


        public ListView() {
            this.ItemTapped += this.OnItemTapped;
        }


        public ICommand ItemClickCommand {
            get { return (ICommand)this.GetValue(ItemClickCommandProperty); }
            set { this.SetValue(ItemClickCommandProperty, value); }
        }


        private void OnItemTapped(object sender, ItemTappedEventArgs e) {
            if (e.Item != null && this.ItemClickCommand != null && this.ItemClickCommand.CanExecute(e)) {
                this.ItemClickCommand.Execute(e.Item);
                this.SelectedItem = null;
            }
        }
    }
}

Ma page XAML

<ContentPage ...
             xmlns:local="clr-namespace:Samples.Views;Assembly=Your Assebly Name">

<local:ListView ItemClickCommand="{Binding Select}" 
        ItemsSource="{Binding List}">

Et dans mon modèle de vue [Dans cet exemple, je n'ai ouvert que la feuille d'action de dialogue

private Command<Signature> selectCmd;
        public Command<Signature> Select {
            get {
                this.selectCmd = this.selectCmd ?? new Command<Signature>(s => 
                    this.dialogs.ActionSheet(new ActionSheetConfig()
                        .Add("View", () => {
                            if (!this.fileViewer.Open(s.FilePath))
                                this.dialogs.Alert(String.Format("Could not open file {0}", s.FileName));
                        })
                        .Add("Cancel")
                    )
                );
                return this.selectCmd;
            }
        }
26
Nirav Mehta

Vous pouvez également utiliser un comportement attaché

public static class ListViewAttachedBehavior
{
    public static readonly BindableProperty CommandProperty =
        BindableProperty.CreateAttached (
            "Command",
            typeof(ICommand),
            typeof(ListViewAttachedBehavior),
            null,
            propertyChanged:OnCommandChanged);

    static void OnCommandChanged (BindableObject view, object oldValue, object newValue)
    {
        var entry = view as ListView;
        if (entry == null) 
            return;

        entry.ItemTapped += (sender, e) => 
            {
                var command = (newValue as ICommand);
                if(command == null)
                    return;

                if(command.CanExecute(e.Item))
                {
                    command.Execute(e.Item);
                }

            };
    }
}

Appelez-le ensuite sur votre ListView

 <ListView
        RowHeight="70"
        x:Name="AcquaintanceListView"
        b:ListViewAttachedBehavior.Command="{Binding ItemSelectedCommand}"
        ItemsSource="{Binding Acquaintances}">
8
Chris Lamothe