【问题标题】:Bot framework - How can I create a Searchable ListBot 框架 - 如何创建可搜索列表
【发布时间】:2019-03-16 02:09:59
【问题描述】:

我可以理解 bot 框架在它提供的控件方面还不成熟, 我正在尝试向用户显示选项列表。当列表有更多元素时,只会显示前 5 个元素,外加一个查看更多元素的选项,该选项将显示所有带有搜索文本框的项目以避免滚动。 因此,我正在尝试实现一个可搜索的列表。查看机器人框架,但提示和自适应卡不是很有用,或者如果我错过了一些东西,得到一些帮助会很好。

注意 - 我正在使用机器人框架 v3

谢谢

【问题讨论】:

    标签: botframework adaptive-cards adaptive-design


    【解决方案1】:

    我把它放在一起。它做的事情类似于你想做的事情。它允许您将列表传递给它,然后它会显示一个提示对话框,其中包含一组选项,让您选择新的搜索以及下一个和上一个。

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

    【讨论】:

    • 太棒了,那是快速而有用的@kjr1995。至少,我正在为列表分页。将尝试探索 SearchTextbox 集成。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 2015-01-10
    • 2023-03-05
    • 2017-01-15
    • 2020-03-12
    • 2012-05-14
    • 1970-01-01
    相关资源
    最近更新 更多