Trigger an action to start after X milliseconds

2019-04-04 08:49发布

I'm developing a Xamarin Forms mobile app, which has a page containing a SearchBar, a ListView, and Map control. The list view contains a list of addresses, which are reflected as pins on the map.

As the user types in the SearchBar, the ListView is automatically updated (through ViewModel binding). The ViewModel method that filters the datasource for the list looks something like this...

void FilterList()
{
    listDataSource = new ObservableCollection<location>(
        locationData.Where(l => l.Address.Contains(searchBar.Text))
    );

    // ***** Now, update the map pins using the data in listDataSource
}

I want to update the Map as the ListView is filtered, but not on EVERY keypress as that could happen multiple times a second. Essentially, I want a "rolling pause" in each FilterList event before the Map is updated. In pseudo-code...

    // ***** Now, update the map pins using the data in listDataSource
    if (a previously-requested map update is pending)
    {
        // Cancel the pending map update request
    }

    // Request a new map update in 1000ms using [listDataSource]

It's possible to do this using the Stopwatch class, which is available in Portable Class Libraries, but I suspect there's a cleaner/better way to accomplish this using Tasks.

Can anyone suggest a "cleverer" PCL-compatible way to do this?

4条回答
贪生不怕死
2楼-- · 2019-04-04 09:13

Just like you said this can be accomplished in a very clean way using Tasks and async programming.

You will want to read about it: http://msdn.microsoft.com/en-us/library/hh191443.aspx

Here's an example:

public async Task DelayActionAsync(int delay, Action action) 
{
    await Task.Delay(delay);

    action();
}
查看更多
Evening l夕情丶
3楼-- · 2019-04-04 09:14

you can try :

await Task.Delay(2000);
查看更多
手持菜刀,她持情操
4楼-- · 2019-04-04 09:22

Here is what I've done and it works in my Xamarin Form apps.

    public string Search
    {
        get { return _search; }
        set
        {
            if (_search == value)
                return;

            _search = value;
            triggerSearch = false;
            Task.Run(async () =>
            {
                string searchText = _search;
                await Task.Delay(2000);
                if (_search == searchText)
                {
                    await ActionToFilter();
                }
            });
        }
    }

I've this 'Search' Property binded to my Entry field. Whenever the user filters something, code waits for 1 second and then compares the new Text field with the field it was before 1 second before. Assuming the string is equal implies that user has stopped entering the text and code can now be triggered to filter.

查看更多
小情绪 Triste *
5楼-- · 2019-04-04 09:38

Working in latest xamarin version.

Another Great method way on button click is ,

    public async void OnButtonClickHandler(Object sender, EventArgs e)
{
    try
    {
        //ShowProgresBar("Loading...");

        await Task.Run(() =>
        {
            Task.Delay(2000); //wait for two milli seconds

            //TODO Your Business logic goes here
            //HideProgressBar();

        });

        await DisplayAlert("Title", "Delayed for two seconds", "Okay");

    }
    catch (Exception ex)
    {

    }
}

async and await keys are important, suppose if you working on multithread environment.

查看更多
登录 后发表回答