Textbox 中的 TextChanged 事件不按顺序出现

TextChanged events from Textbox don't come in order

提问人:jdonkers 提问时间:4/27/2022 更新时间:4/28/2022 访问量:157

问:

我正在尝试根据用户输入字符时输入到 TextBox 中的数字动态过滤数据。我发现文本值似乎乱序了,我不知道为什么。例如,如果文本框中已经有“1379”,然后我输入“2019”(所以以“13792019”结尾),我会得到以下内容:

    TxtFilter_TextChanged; text 13792; Time: 637865675822596714
    TxtFilter_TextChanged; text 1379201; Time: 637865675846017202
    TxtFilter_TextChanged; text 13792019; Time: 637865675847734984
    TxtFilter_TextChanged; text 137920; Time: 637865675849383373

我正在以刻度记录时间。我肯定可以看到这些值正在增加,但我不知道为什么/如何“137920”在“13792019”之后出现?我可以始终如一地重现这一点。

现在,我使回发在键入时发生,以便我可以将焦点设置回文本框上。在 OnFocus 上,我将光标设置到最后一个位置(否则它会返回到起点)。我愿意有更好的方法来做到这一点......

<script type="text/javascript">
function RefreshUpdatePanel(e) {
    __doPostBack('<%= txtFilter.ClientID %>', '');
    document.all.txtFilter.focus();
};

function SetEnd(txt) {
    if (txt.createTextRange) {
        //IE  
        var FieldRange = txt.createTextRange();
        FieldRange.moveStart('character', txt.value.length);
        FieldRange.collapse();
        FieldRange.select();
    }
    else {
        //Firefox and Opera  
        txt.focus();
        var length = txt.value.length;
        txt.setSelectionRange(length, length);
    }
}

代码隐藏:LoadOrderList 方法根据筛选的文本绑定数据,然后加载所选第一项(如果有)的订单信息。

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        txtFilter.Attributes.Add("OnFocus", "SetEnd(this);");
        txtFilter.Attributes.Add("OnKeyUp", "RefreshUpdatePanel();");

        LoadOrderList();
    }
}

protected void TxtFilter_TextChanged(object sender, EventArgs e)
{
    DateTime dtNow = DateTime.Now;
    System.Diagnostics.Trace.WriteLine(string.Format("TxtFilter_TextChanged; text {0}; Time: {1}", ((TextBox)sender).Text, dtNow.Ticks));
    LoadOrderList();
}
C# asp.net 事件 文本框

评论

1赞 fnostro 4/27/2022
我不相信回发事件顺序是有保证的。无论如何,您真的想在每次键入时进行回发吗?也许使用 blur 事件,等待所有文本并回发一次。
0赞 jdonkers 4/27/2022
是的,用户希望在键入时看到被筛选的结果。正如你所说,我宁愿以另一种方式做。
0赞 pcalkins 4/27/2022
设置光标位置非常古怪,尤其是在浏览器上。您可以尝试删除“ txt.focus();”,看看是否有帮助。
1赞 fnostro 4/27/2022
哎哟!并带有更新面板,双哎哟。也许可以考虑在收集几次击键后回发,过滤单个字母可能会产生一个大型数据集。此外,请考虑仅返回前 X 行。
0赞 Caius Jard 4/27/2022
同意fnostro;仅当用户在过去 500 毫秒内未键入任何内容时才运行搜索;相关的搜索词可能是“debounce”

答:

0赞 Albert D. Kallal 4/28/2022 #1

我不会在这里做一整页的回帖。需要执行 Web API 调用,传递文本框,获取响应。你使用过ajaxtoolkit吗?它有一个自动完成的预构建,并允许您设置时间/延迟,甚至您必须输入的字符数。

现在,我可能不想为这个 ONE 功能采用整个 ajaxtoolkit,但我肯定会考虑工具包 - 因为自动完成确实工作得很好,并且自动魔术为您连接了 ajax 调用 - 没有页面回发。

而且它易于使用。

您还可以获得多选择组合框,这是一个非常光滑的对话框(比 bootstratp 或 jquery.ui 更容易使用)。你会得到非常好的上传者。

因此,请考虑ajaxtoolkit。它当然已经过时了,但如果你的项目仍然是 Web 表单,那么我会考虑采用工具包,因为那时你可以有一个有效的自动完成示例和工具——一个经过战斗强化的、你知道的、运行良好的。

事实上,请注意这里的房间里有一头大象吗?

这是什么?

为什么当然没有人愿意发布他们的工作示例,并建议/展示他们用于这个非常常见的任务和功能。

而且由于没有人发布示例,那么这在很大程度上意味着设置此类示例所需的时间和精力比在 SO 上发布所需的时间要多。

如果展示这样的例子所花费的时间更多,那么在 SO 上发布作为简单答案需要什么?

你失败了!!- 换句话说,你不仅现在想要这种功能,而且接下来的 10 个例子你想再次这样做呢?再说一遍???

那么真正的目标,真正的答案是什么?

无论您走什么路和哪条路,您最想走的是一条可以反复使用工作解决方案的道路。

所以,假设我想搜索一些酒店名称。所以,放下;在文本框中,然后单击 Ajax 工具包扩展器。

所以,我放了一个文本框,然后去:

enter image description here

现在,选择自动完成

enter image description here

所以,现在我的标记是这样的

    <font size="4">Search for Hotel : </font>
    <asp:TextBox ID="txtHotel" runat="server" Width="250px">
    </asp:TextBox>  

        <ajaxToolkit:AutoCompleteExtender
            ID="txtHotel_AutoCompleteExtender" runat="server" 
            BehaviorID="txtHotel_AutoCompleteExtender" DelimiterCharacters="" 
            ServiceMethod = "GetHotels"
            MinimumPrefixLength="1"
            TargetControlID="txtHotel">
        </ajaxToolkit:AutoCompleteExtender>

背后的代码呢?这:

    [WebMethod()]

    public static List<string> GetHotels(string prefixText, int count)
    {
        List<string> Hotels = new List<string>();
        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))                
        {
            string strSQL 
                = "SELECT HotelName FROM tblHotels " +
                   "WHERE HotelName like @SearchText + '%' " +
                   "ORDER BY HotelName";
            using (SqlCommand cmd = new SqlCommand(strSQL,conn))
            {
                cmd.Parameters.Add("@SearchText", SqlDbType.NVarChar).Value = prefixText;
                conn.Open();
                using (SqlDataReader sdr = cmd.ExecuteReader())
                {
                    while (sdr.Read())
                        Hotels.Add(sdr["HotelName"].ToString());
                }
            }
        }
        return Hotels;
    }

现在我们有了这个:

enter image description here

你会得到一个完整的属性表 - 你可以自定义交易,前缀长度 - 所有的设置和设置都为你完成。

因此,您有以下设置:

enter image description here

因此,有“现有”工具可以做到这一点。

但我认为不仅仅是出去挑选任何旧工具?

真正的交易,真正的问题?

你有没有一个工具,让你花时间在SO上回答一个问题,展示一个工作的例子???

没有其他人愿意这样做的事实?

这并不意味着他们是卑鄙的人、坏人,甚至是懒惰的人。

但这确实意味着他们没有选择一个解决方案,为您提供向导、助手和内置的 UI 设计师,允许我在接近创纪录的时间内完成所有这些工作,因为我使用了一个非常简单的解决方案。

评论

0赞 pcalkins 4/28/2022
不太确定 OP 是否显示列表...他们不必为此设置光标位置。似乎它们在文本框内自动建议......(实施起来更痛苦)
0赞 Albert D. Kallal 4/28/2022
好吧,它确实会在您输入时自动建议 - 所谓的“列表”是自动为文本框创建的 - 这就是谷歌的工作方式 - 开始输入,您会看到一个匹配列表出现在下面。因此,谷歌被人们普遍使用,它的自动完成“概念”确实显示了下面的列表。所以,我想这取决于什么样的自动完成 - 但你的观点是公平的 - ajax 自动完成加载项的工作方式与谷歌非常相似,有些显然不显示下面的列表,而只是在文本框中显示结果。Jquery.UI(来自同一个jQuery人员)也有下面的列表。因此,大多数显示列表如下。
0赞 pcalkins 4/29/2022
是的,不太确定这里的预期行为是什么......因为 OP 使用的是 setSelectionRange,所以他们似乎在做更像 gmail 的事情,在您输入时,建议会出现在文本框中。从帖子中有点不清楚。如果它是标准列表类型,那么它们应该只需要 .focus()。