Bot Framework - Как я могу создать список для поиска - PullRequest
0 голосов
/ 11 октября 2018

Я понимаю, что бот-фреймворк еще не достиг зрелости с точки зрения элементов управления, которые он предоставляет, я пытаюсь отобразить список опций для пользователя.Если в списке больше элементов, будут отображаться только первые 5 элементов, а также опция для просмотра большего количества элементов, в которых будут отображаться все элементы с текстовым полем поиска, чтобы избежать прокрутки.Поэтому я пытаюсь реализовать список поиска.Посмотрел в рамках бота, но подсказки и адаптивные карты не очень полезны, или если я что-то пропустил, было бы здорово получить некоторую помощь.

Примечание - я использую бот-фреймворк v3

Спасибо

1 Ответ

0 голосов
/ 11 октября 2018

Я собрал это вместе.Это делает что-то похожее на то, что вы хотите сделать.Он позволяет вам передать в него список, а затем отображает диалоговое окно с заданным количеством параметров, позволяющее выбрать новый поиск, а также следующий и предыдущий.

[Serializable]
public class OptionsDialog<T> : IDialog<OptionsResult<T>>
    where T : class
{
    private const string CurrentPage = "currentPage";

    private readonly IList<T> _items;

    private readonly Func<T, string> _descriptionFunc;

    private readonly Func<T, IReadOnlyList<string>> _synonymFunc;

    private readonly string _prompt;

    private int current = 0;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="items">Must be a distinct list</param>
    /// <param name="descriptionFunction">Function to get the description for an option</param>
    /// <param name="synonymFunction">Function to get the synonyms for an option</param>
    /// <param name="prompt">Prompt for the options</param>
    public OptionsDialog(IList<T> items, Func<T, string> descriptionFunction, Func<T, IReadOnlyList<string>> synonymFunction, string prompt)
    {
        _items = items;
        _descriptionFunc = descriptionFunction;
        _synonymFunc = synonymFunction;
        _prompt = prompt;
    }

    public Task StartAsync(IDialogContext context)
    {
        if (_items.Count() == 0)
        {
            context.Done(new OptionsResult<T>(null, false));
        }
        else if (_items.Count() == 1)
        {
            context.Done(new OptionsResult<T>(_items.First(), false));
        }
        else
        {
            SendContactOptions(context, _items);
        }

        return Task.CompletedTask;
    }

    private void SendContactOptions(IDialogContext context, IList<T> items)
    {
        int maxContacts = int.Parse(ConfigurationManager.AppSettings["MaxContactsShown"]);
        bool addNext = false;
        bool addPrevious = false;
        if (items.Count > maxContacts)
        {
            if (current > 0)
            {
                addPrevious = true;
            }

            if (items.Skip(current * maxContacts).Count() > maxContacts)
            {
                addNext = true;
            }

            items = items.Skip(current * maxContacts)
                               .Take(maxContacts)
                               .ToList();
        }

        List<string> descriptions;
        Dictionary<string, IReadOnlyList<string>> choices;

        descriptions = items.Select(item => _descriptionFunc(item)).ToList();

        choices = items.ToDictionary<T, string,
            IReadOnlyList<string>>(item => item.ToString(), item => _synonymFunc(item));

        if (addNext)
        {
            descriptions.Add("More");
            choices.Add("More", new List<string>() { "Next" });
        }

        if (addPrevious)
        {
            descriptions.Add("Previous");
            choices.Add("Previous", new List<string>() { "Previous", "Last", "Back" });
        }

        descriptions.Add("New Search");
        descriptions.Add("Cancel");

        choices.Add("New Search", new List<string>() { "None", "None of these", "Next Search", "Search Again", "Search" });
        choices.Add("Cancel", new List<string>() { "Stop", "Quit" });

        IPromptOptions<string> promptOptions = new PromptOptionsWithSynonyms<string>(_prompt, choices: choices, descriptions: descriptions,
            tooManyAttempts: DialogHelper.TooManyAttemptsText);
        PromptDialog.Choice(context, SelectItemAsync, promptOptions);
    }

    private async Task SelectItemAsync(IDialogContext context, IAwaitable<object> result)
    {
        try
        {
            string contactName = await result as string;

            if (contactName == "Cancel")
            {
                context.Done(new OptionsResult<T>(null, false, true));
            }
            else if (contactName == "New Search")
            {
                context.Done(new OptionsResult<T>(null, true));
            }
            else if (contactName == "More")
            {
                current++;
                SendContactOptions(context, _items);
            }
            else if (contactName == "Previous")
            {
                current--;
                SendContactOptions(context, _items);
            }
            else
            {
                T resultItem = _items.FirstOrDefault(c => c.ToString().ToLower() == contactName.ToLower());

                if (resultItem != null)
                {
                    DialogHelper.DeleteConversationItem(context, "searchContacts");
                    context.Done(new OptionsResult<T>(resultItem, false));
                }
                else
                {
                    context.Done(new OptionsResult<T>(null, false));
                }
            }
        }
        catch (TooManyAttemptsException)
        {
            context.Done(new OptionsResult<T>(null, false));
        }
    }
}


[Serializable]
public class OptionsResult<T>
    where T : class
{
    /// <summary>
    /// Result of the options
    /// </summary>
    public T Result { get; set; }

    /// <summary>
    /// Whether the parent dialog needs to search again
    /// </summary>
    public bool SearchAgain { get; set; }

    public bool IsCancelled { get; set; }


    public OptionsResult(T result, bool searchAgain, bool cancelled = false)
    {
        Result = result;
        SearchAgain = searchAgain;
        IsCancelled = cancelled;
    }
}
...