web-dev-qa-db-fra.com

Liaison de commandes ListView ItemTapped / ItemSelected de Xamarin Forms sur XAML

Comment puis-je lier un objet ICommand de mon ViewModel (actuellement dans BindingContext) à ItemTapped ou ItemSelected à partir d'une ListView en XAML?

C'est une tâche simple lors de l'utilisation d'un bouton, je viens de définir Command = "MyViewModelCommand" et tout fonctionne.

18
MarcioGomes

Je ne sais pas pourquoi vous devez donner l'événement Item Selected ou Item Tapped dans votre page lorsque vous pouvez directement obtenir l'objet sélectionné/tapé directement dans votre ViewModel:

Je pense que vous avez lié la liste avec les types de code ci-dessous

<ListView ItemsSource="{Binding PermitDetails}" 
SelectedItem="{Binding objItemSelected, Mode=TwoWay}" x:Name="lst" 
RowHeight="35" HorizontalOptions="FillAndExpand" 
VerticalOptions="Fill">

Et dans le modèle d'affichage que vous avez lié à la page, vous devez définir la propriété objItemSelected comme mentionné dans le code ci-dessous

private Permit _ItemSelected;
public Permit objItemSelected {
    get {
        return _ItemSelected;
    }
    set {
        if (_ItemSelected != value) {
            _ItemSelected = value;
            OnPropertyChanged ("ItemSelected");
        }
    }
}

Et si vous souhaitez effectuer des fonctionnalités supplémentaires telles que la navigation vers la page de détails, vous pouvez le faire à partir de la propriété set après l'exécution de l'instruction OnPropertyChanged.

J'espère que cela t'aides!

25
Nirav Mehta

J'avais l'habitude d'adopter l'approche de liaison de l'élément sélectionné dans le modèle de vue, mais cela avait tendance à soulever des problèmes de filtrage des modifications de programme par rapport à l'action de l'utilisateur. Mon préféré est une propriété attenante.

public static readonly BindableProperty ListItemTappedCommandProperty = BindableProperty.CreateAttached<AttachedProperties, ICommand>(
    staticgetter: o => (ICommand) o.GetValue(ListItemTappedCommandProperty), 
    defaultValue: default(ICommand),
    propertyChanged: (o, old, @new) =>
    {
        var lv = o as ListView;
        if (lv == null) return;

        lv.ItemTapped -= ListView_ItemTapped;
        lv.ItemTapped += ListView_ItemTapped;
    });

private static void ListView_ItemTapped(object sender, object item)
{
    var lv = sender as ListView;

    var command = (ICommand) lv?.GetValue(ListItemTappedCommandProperty);
    if (command == null) return;

    if (command.CanExecute(item))
        command.Execute(item);
}

... puis définissez sur un ListView avec:

controls:AttachedProperties.ListItemTappedCommand="{Binding ItemSelectedCommand}"

Il est possible que cela soit même étendu pour prendre le nom de l'événement et s'appliquer plus généralement, mais c'est un exercice pour une autre fois.

3
Adam Hewitt

Mon scénario est un clavier et les images sont les boutons et lorsque l'on clique dessus, le caractère correspondant est affiché sur une étiquette.

Donc..

Disons que vous avez le contrôle de suivi (touche 1):

<Image  x:Name="imgKey1"
        Source="key1.png"
        Aspect="AspectFit" />

Et vous voulez quand l'image est tapée pour déclencher une commande de votre objet "viewModel". Mon "viewModel" a la propriété suivante:

public ICommand AddCharCommand { protected set; get; }

où dans mon constructeur de classe (voir le modèle) j'ai:

  this.AddCharCommand = new Command<string>((key) =>
            {
                // Add the key to the input string.
                this.InputString += key;
            });

"InputString" est une propriété de chaîne ...

Donc, pour lier la vue et le mode, je fais ce qui suit:

  imgKey1.GestureRecognizers.Add(new TapGestureRecognizer
        {
            Command = viewModel.AddCharCommand,
            CommandParameter = "1",
        });

J'espère que je vous aide, si quelqu'un a besoin de quelque chose et que je peux vous aider; je suis ici ... et là. JJ

EN XAML 17-11-14

      <Image  Source="n1normal.png"
              Aspect="AspectFit" >
        <Image.GestureRecognizers>
          <TapGestureRecognizer
            Command="{Binding AddCharCommand}"
            CommandParameter ="1"/>
        </Image.GestureRecognizers>
      </Image>

//-OR-

        <Image Source="magnifyglass.png"
               Aspect="AspectFit"
               HorizontalOptions="End">
          <Image.GestureRecognizers>
            <TapGestureRecognizer Tapped="Search"/>
          </Image.GestureRecognizers>  
        </Image>

//And for the Search create in your ViewModel

 private void Search(object sender, EventArgs e)
 {
      //Your code here
 }
3
JohnnyJaxs

Pourquoi ne pas lier l'attribut selectedItem de votre listview à une propriété viewModel (disons une propriété 'selectedItem'); puis sur le setter pour la propriété 'selectedItem' dans votre viewModel vous exécutez votre commande.

0
Madol

C'est une vieille question, et c'est peut-être un développement assez récent, mais vous pouvez utiliser les comportements sur n'importe quel contrôle pour convertir un événement en ICommand.

Un exemple...

<ListView ItemsSource="{Binding Tags}"
            SelectedItem="{Binding SelectedTag}">
    <ListView.Behaviors>
        <behaviors:EventHandlerBehavior EventName="ItemSelected">
            <behaviors:InvokeCommandAction Command="{Binding SelectedTagChanged}" />
        </behaviors:EventHandlerBehavior>
    </ListView.Behaviors>
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <ContentView Padding="8">
                    <Label Text="{Binding DisplayValue}" />
                </ContentView>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Dans cet exemple, l'événement ItemSelected sera mappé à la commande SelectedTagChanged dans votre modèle de vue qui ressemble à ceci ...

public Command SelectedTagChanged
{
    get
    {
        return new Command(() =>
        {
            // do something
        });
    }
}
0
John Livermore