从 AutoCompleteExtender 中选择某种类型的项目时,启用 ASP.NET AutoCompleteExtender 的 TextBox 的 TextChanged 事件不会触发(哇...)
今天我遇到了一个非常奇怪的问题,由存储过程、自动完成扩展程序和事件处理组成。如果有人能为以下传奇故事提供一个简洁的标题,请这样做!
首先我会尝试介绍玩家(有些部分有点删节),然后介绍场景。环境为VS2008、C#、SQL Server 2005和ASP.NET。
数据库表:
TABLE (
SomeNbr INT,
SomeAbbr VARCHAR(10),
Name VARCHAR(30)
)
StoredProcedure:
读取上表并返回如下内容:
DECLARE @Results TABLE
(
SomeNbr INT,
--Composite CHAR(50), -- voodoo magic starts here...
Composite VARCHAR(50)
)
返回表的复合字段由 SomeNbr、SomeAbbr 和 Name 字段组成。它们附加在一起并用逗号分隔(例如“编号、缩写、名称”)。
存储过程用于从数据库检索一组行,并将这些行放入类型化数据表中。然后将该数据表存储在会话变量中。 DataTable 的 XSD-Schema 的“Composite”字段的数据类型为 String。
!重要的!对于数据库中的某些行,“名称”字段包含实际值和填充(由空格组成)直至最大长度。其他仅包含名称,没有填充。
用户界面(带有代码隐藏的 ASPX 页面):
我已经扩展了文本框控件,以包含 AJAX Control Toolkit 中的 AutoCompleteExtender。控件声明如下:
<ajx:TextControl ID="txtControl"
runat="server"
AutoPostBack="true"
UseAutoComplete="true"
ServiceMethod="GetItems"
MinimumPrefixLength="1" />
ui 上还有一些附加的基本文本框。
CodeBehind:
AutoCompleteExtender 使用以下 Web 方法:
[System.Web.Services.WebMethod]
public static string[] GetItems(string prefixText, int count)
{
try
{
return Utility.GetMatchingStrings(_DataTableInSession, prefixText);
}
catch (Exception ex)
{
throw;
}
}
GetMatchingStrings(...) - 方法将 preFixText 与 _DataTableInSession 中的所有数据行进行比较,并返回匹配字符串的数组。比较是通过数据行的“复合”字段完成的。
在代码隐藏中,事件处理程序被设置:
extendedTextControl.Control.TextChanged += PopulateTextControls;
和:
private void PopulateTextControls(object sender, EventArgs e)
{
// Read Text-property from extended textcontrol
string str = extendedTextControl.Text;
// Split string by commas and take parts into an array
string[] arrStr = SplitString(",", str);
// Set the values in array to Text-properties of TextBoxes
SetValuesToTextBoxes(arrStr, _TextBoxes);
}
场景
一切似乎都很好,扩展的 TextControl 正在按预期工作,并在文本框下方生成可选择列表。
场景 1:
现在,当用户从自动完成列表中选择一个项目时,会发生以下情况:
- 所选字符串设置为扩展文本控件的文本属性,
- 文本控件的自动回发
- 在回发时发生,为文本控件的 TextChanged 注册了一个事件处理程序-event
- TextChanged-事件被触发,其他文本框按预期填充数据
要发生这种情况,键入的数据行中的“Composite”字段必须是这样的:
“10”,“10,ABBR,Some Name” Goes Here____..._"(<- 空格替换为下划线)
如果数据行更像是这样:
“10”、“10、ABBR、Some Name Goes Here”,
那么我们将转到...
场景 2:
以上是一种快乐的一天 - 场景 :-)
如果 匹配的数据行是由数据库中的“名称”字段不是<的行组成的/em> 用空格填充直至最大长度 (VARCHAR(50)),然后 TextChanged 事件不会被触发。
我花了好几个小时试图弄清楚上面的一切。首先,我很困惑为什么选择自动完成列表中的某些项目确实起作用,而有些则不起作用。
当我意识到要查看数据表的内容时,我发现有些行有填充,而其他行则没有。之后,我尝试 ltrim(rtrim()) SP 返回表中的所有内容,但所有项目都不再起作用。
之后,我尝试将 SP 的返回值设置为 CHAR(50) 而不是 VARCHAR(50),并且修复了该问题。
问题:
我的应用程序发生了什么?为什么注册的事件没有触发?就像 TextChanged 只适用于特定长度的字符串(VARCHAR(50) 的最大长度),但这怎么可能呢?
问题解决了,但我不知道为什么。我想,又是在办公室度过的一天:-)
我很乐意提供额外的数据和说明!
编辑 1: 添加了有关数据行中空格和下划线的注释。
Today i faced a pretty weird problem, made of a stored procedure, an autocompleteextender and event handling. If anyone can suggest a concise title for the following saga, please do!
First i'll try to introduce the players (some parts are a bit abridged) and then the scenarios. Environment is VS2008, C#, SQL Server 2005 and ASP.NET.
DB table:
TABLE (
SomeNbr INT,
SomeAbbr VARCHAR(10),
Name VARCHAR(30)
)
StoredProcedure:
Reads the table above and returns something like this:
DECLARE @Results TABLE
(
SomeNbr INT,
--Composite CHAR(50), -- voodoo magic starts here...
Composite VARCHAR(50)
)
Composite-field of the return table is made of SomeNbr, SomeAbbr and Name fields. They are appended together and separated by commas (f.ex. "number, abbreviation, name").
Stored Procedure is used to retrieve a set of rows from db, and these are put into a typed datatable. This datatable is then stored in a session variable. DataTable's XSD-Schema has datatype String for the "Composite"-field.
!Important! For some rows in the db, "Name"-field contains the actual value and rpadding (made of spaces) up to the maximum length. Other just contain the name with no rpadding.
User interface (ASPX-page with codebehind):
I have extended textbox-control to include an AutoCompleteExtender from AJAX Control Toolkit. Control is declared as follows:
<ajx:TextControl ID="txtControl"
runat="server"
AutoPostBack="true"
UseAutoComplete="true"
ServiceMethod="GetItems"
MinimumPrefixLength="1" />
There are some additional basic textboxes on the ui.
CodeBehind:
AutoCompleteExtender uses the following webmethod:
[System.Web.Services.WebMethod]
public static string[] GetItems(string prefixText, int count)
{
try
{
return Utility.GetMatchingStrings(_DataTableInSession, prefixText);
}
catch (Exception ex)
{
throw;
}
}
GetMatchingStrings(...)-method compares preFixText against all datarows in _DataTableInSession, and returns an array of matching strings. Comparison is done with the datarows' "Composite"-fields.
In codebehind, the event handler gets set:
extendedTextControl.Control.TextChanged += PopulateTextControls;
, and:
private void PopulateTextControls(object sender, EventArgs e)
{
// Read Text-property from extended textcontrol
string str = extendedTextControl.Text;
// Split string by commas and take parts into an array
string[] arrStr = SplitString(",", str);
// Set the values in array to Text-properties of TextBoxes
SetValuesToTextBoxes(arrStr, _TextBoxes);
}
Scenarios
Everything seems to be fine, the extended TextControl is working as it is supposed to and generates the selectable list below the textbox.
Scenario 1:
Now, when user selects an item from autocompletion list the following things happen:
- Selected string is set to Text-property of the extended textcontrol
- textcontrol's autopostback happens
- on postback, an eventhandler is registered for textcontrol's TextChanged-event
- TextChanged-event is fired and other textboxes get filled with data as expected
For this scenario to happen, the "Composite"-field in the typed datarow has to be something like this:
"10", "10, ABBR, Some Name Goes Here____..._" (<- spaces replaced with underscores)
If the datarow is more like this:
"10", "10, ABBR, Some Name Goes Here"
then we'll go to...
Scenario 2:
The above is a sort of happy day -scenario :-)
If the matching datarow is made from a row in db where "Name"-field is not padded with spaces up to the maximum length (VARCHAR(50)), then the TextChanged-event does not get fired.
I spent a good few hours trying to figure out everything above. First i was quite confused that why the **** selecting some of the items in autocompletion list do work, and some don't.
When i realized to look at the datatable's contents, i saw that some rows had the padding and others did not. After that i tried to ltrim(rtrim()) everything in the SP's return table, and none of the items worked anymore.
After that i tried to set the SP's return value to CHAR(50) instead of VARCHAR(50), and that fixed it.
Question:
What is going on in my application? Why doesn't the registered event fire? It's like TextChanged would only work for string of certain length (max length of the VARCHAR(50)), but how would that be possible?
Problem is solved, but i have no idea why. Just another day at the office, i suppose :-)
I'll be happy to provide additional data and clarifications!
Edit 1: Added note about spaces and underscores within the datarow.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不理解整个场景,但我会看看 CHAR(50) 与 VARCHAR(50) 问题。我也不知道“WebOlkiUtility.GetMatchingStrings”的作用。
CHAR(50) 始终返回 50 个字符!
顺便说一句:为什么你要这样附加事件?
您可以随时附加它。在您的 ASPX 文件或 Page_Init 方法中。
I didn't understand the whole scenario but I would look at the CHAR(50) vs. VARCHAR(50) issue. I also do not know what "WebOlkiUtility.GetMatchingStrings" does.
CHAR(50) returns always 50 Character!
BTW: Why do you attach the event this way?
You could attach it always. In your ASPX file or in the Page_Init Method.