How can I tell if an ItemTapped was clicked?

2

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

When clicked on above an item from my ListView another screen at that time is called and unfortunately the ListView screen still keeps updating every 30 seconds, I would like that at that time this 30 in 30 seconds it stopped. I could solve this with an'if ', but for this I need to know when ItemTapped was triggered, which I do not 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;
}
    
asked by anonymous 28.08.2018 / 22:53

3 answers

1

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

It was not clear that you want this function to be interrupted only while the user enters the Lance screen or if once an item was selected the list would not be updated any more, so I'll show you how it can be done for the two cases.

Pausing the update while the new screen was opened

First let's put an external variable to the StartTimer function and use it as a 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;
        });
}

Next, when you trigger the OnItemTapped event, you assign a value to the someItemTapped variable:

//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 it with the pause effect. If it's just to stop the update after the click, you do not need it. *

Finally, let's adjust how you initialize the timer function. I'm not sure where you call it, but it should be in the builder. To work with the pause effect, you would need to start it every time the page is displayed, that is, OnAppearing :

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

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

    base.OnAppearing();
}

I hope I have helped.

    
02.09.2018 / 18:11
2

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

First we will create our 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 an attribute of the class to use at two different points, then we will have our timer executed in its Timer method:

private CustomTimer _timer;

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

    _timer.Start();
}

At this point we have our timer running every 30 seconds, now we need to cancel the execution when we click on your TempoAtualiza() , for this we will use the ListView method 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 have helped!

    
01.09.2018 / 01:59
0

I do not have much information about your project but this example can help

  

xaml

 <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 deep down would be through the OnItemTapped

I can also 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");
}

It's still events in this expensive ItemTapped and ItemSelected

When they occur they trigger a message on the screen.

    
31.08.2018 / 13:37