How do I know if an Itemtapped has been clicked?

Asked

Viewed 148 times

2

I have a ListView with a function so that every 30 seconds ListView be updated.

When it is triggered click on an item of mine ListView another screen at that time is called and unfortunately the screen of ListView It’s still being updated every 30 seconds, so I’d like this update every 30 seconds to stop. I could solve this with an if , but for that I need to know when the ItemTapped has been triggered, which I don’t know how to implement.

My Listview:

<!-- Listagem de Produtos -->
<ListView x:Name="lstLeilao" 
          ItemTapped="OnTapLance">

    <ListView.ItemTemplate>
        <!-- DataTemplate  = exibe dados de uma coleção de objetos em um ListView -->
        <DataTemplate>
            <ViewCell>
                ... 

                <!-- Grid de exibição -->

                ...
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

The function that counts 30 seconds:

//A cada 30 segundos atualiza a tela Leilão Aberto
public void TempoAtualiza()
{
    Device.StartTimer ( TimeSpan.FromSeconds(30), () =>
        {
            if (OnTapLance == true) //AQUI QUE EU IMPLEMENTARIA A FUNÇÃO
                return false;

            AtualizaDados(usuario);
            return true;
        });
}

The click function:

//Toque
public void OnTapLance(object sender, ItemTappedEventArgs e)
{
    isLoading = true;
    var item = (sender as ListView).SelectedItem as LeilaoObjeto;

    Navigation.PushAsync(new Lance(Convert.ToInt32(item.ID_LEILAO)));
    isLoading = false;
}
  • Friend your question is very confused. Attention to your if you only have one =, if you want to compare values you have to put if (ItemTapped == true) . But since you are comparing to true (true) you can also put if (ItemTapped)

  • In fact if is just an example, it is not a functional code. Itemtapped is an event that is triggered when touching the item in Listview, I need to know whether or not someone touched an item in Listview, what my question means.

  • 1

    To facilitate then @Iazyfox I took the example and put the real application.

3 answers

2

We can create a Timer customized and in it we will have a CancellationTokenSource, where we will register our event to cancel our timer that updates the data with the method AtualizaDados.

First we will create our Timer custom. Create the following class below:

public class CustomTimer
{
    //Objeto que irá representar nosso temporizador, ele irá gravar todas nossas informações de tempo de execução do processo
    private readonly TimeSpan _timeSpan;
    //Delegate que irá conter a nossa função que desejamos que seja executada no nosso temporizador.
    private readonly Action _callback;
    //Token para cancelar o temporizador quando desejado
    private CancellationTokenSource _cancellation;

    /// <summary>
    /// Construtor da temporizador customizado, aqui precisamos passar as informações de tempo e o método que será executado
    /// </summary>
    /// <param name="timeSpan">Passar um TimeSpan com as configurações de tempo</param>
    /// <param name="callback">Passar o método que será executado</param>
    public CustomTimer(TimeSpan timeSpan, Action callback)
    {
        _timeSpan = timeSpan;
        _callback = callback;
        _cancellation = new CancellationTokenSource();
    }

    public void Start()
    {
        CancellationTokenSource cancellationToken = _cancellation;

        Device.StartTimer(_timeSpan, () =>
        {
            //Quando o token de cancelamento for acionado iremos parar o processamento do timer
            if (cancellationToken.IsCancellationRequested)
                return false;

            //Invoca o método que desejamos executar
            _callback.Invoke();

            return true;
        });
    }

    public void Stop()
    {
        //Registramos a intenção de parar o timer no token de cancelamento
        Interlocked.Exchange(ref _cancellation, new CancellationTokenSource()).Cancel();
    }
}

Now that we have our custom timer, we need to create it as a class attribute to use in two different points, then we will have our timer run in your method TempoAtualiza():

private CustomTimer _timer;

public void TempoAtualiza()
{
    _timer = new CustomTimer(TimeSpan.FromSeconds(30), () => 
    { 
        AtualizaDados(usuario);
    });

    _timer.Start();
}

Right now we have our timer running every 30 seconds, now we need to cancel the execution when we click on your ListView, for this we will use the method OnTapLance that you have already created:

public void OnTapLance(object sender, ItemTappedEventArgs e)
{
    isLoading = true;
    var item = (sender as ListView).SelectedItem as LeilaoObjeto;

    //Se o timer já foi instanciado e está sendo executado, iremos executar o método que para a execução.
    if (_timer != null)
        _timer.Stop();

    Navigation.PushAsync(new Lance(Convert.ToInt32(item.ID_LEILAO)));
    isLoading = false;
}

I hope I’ve helped!

1


For its recurring function, it AtualizaDados, you are using the resource Device.StartTimer. From what you can see in your code, you already understand that this function will be repeated while the function returns true.

It is not clear that you want this function to be stopped only while the user enters the Lance or if once an item has been selected the list would no longer be updated, then I will show how it can be done for both cases.

Pausing the update while the new screen was opened

First let’s put an external variable to the function of the StartTimer and use it as return parameter:

bool someItemTapped = false;

...

//A cada 30 segundos atualiza a tela Leilão Aberto
public void TempoAtualiza()
{
    Device.StartTimer ( TimeSpan.FromSeconds(30), () =>
        {
            if (!someItemTapped)
                AtualizaDados(usuario);

            return someItemTapped;
        });
}

Then, when triggering the event OnItemTapped, you assign a value to the variable someItemTapped:

//Toque
public void OnTapLance(object sender, ItemTappedEventArgs e)
{
    someItemTapped = true;
    isLoading = true;
    var item = (sender as ListView).SelectedItem as LeilaoObjeto;

    Navigation.PushAsync(new Lance(Convert.ToInt32(item.ID_LEILAO)));
    isLoading = false;
}

This last step you only need to implement if you want to use with the pause effect. If it’s just to stop the update after clicking, you don’t need to.*

Finally, let’s adjust how you initialize the timer function. I’m not sure where you call it, but it should be in the constructor. In order for it to work with the pause effect, you would need to start it every time the page is displayed, i.e. OnAppearing:

protected override void OnAppearing()
{
    if(someItemTapped)
    {
        someItemTapped = false;

        // Inicializa a função recorrente
        TempoAtualiza();
    }

    base.OnAppearing();
}

I hope I’ve helped.

0

I don’t have much information about your project but this example can help

shaman

 <ListView Grid.Row="1"
                  ItemsSource="{Binding Orders}"
                  VerticalOptions="Fill"
                  x:Name="ListviewOrder">
          <ListView.ItemTemplate>
            <DataTemplate>
              <ImageCell
                  ImageSource="MyImage"
                  Text="{Binding OrderName}"
                  Detail="{Binding OrderNo}">
                <b:Interaction.Behaviors>
                  <b:BehaviorCollection>
                    <b:EventToCommand CommandNameContext="{b:RelativeContext Details}"
                                      EventName="Tapped"
                                      CommandName="SelectCommand"
                                      CommandParameter="{Binding .}" />
                  </b:BehaviorCollection>
                </b:Interaction.Behaviors>
              </ImageCell>
            </DataTemplate>
          </ListView.ItemTemplate>
        </ListView>

c#

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

But in the background it would be through the event Onitemtapped

I can add this other example

listView.ItemTapped += async (sender, e) =>
{
await DisplayAlert("Tapped", e.Item.ToString() + " was selected.", "OK");
};

listView.ItemSelected += async (sender, e) =>
{
await DisplayAlert("Selected", e.SelectedItem.ToString()+ " was selected.", "OK");
}

These are still events in this expensive Itemtapped and the Itemselected

When they occur they fire a message on the screen.

  • I took the example that was to put my real application since it facilitates, but thank you for the examples.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.