我在 asp.net 组件页面上有一个 DropDownList (DDL),用于更改组件页面的所述组件实例的子组件。 DDL(与其他元素一起)位于 UpdatePanel 中,并且 DDL 禁用了 AutoPostBack,因为我们不会推送更改,直到单击页面底部的“提交”按钮,这会触发所述 UpdatePanel 的更新。 DDL 的项目是在页面加载时从数据库中获取的。
<asp:UpdatePanel runat="server">
<ContentTemplate>
<div runat="server" id="ComponentsDiv">
<div runat="server" class="row">
<div class="col-md-6">
<div class="form-group">
<asp:Label runat="server" AssociatedControlID="subcomponentDDL">subcomponent</asp:Label>
<asp:DropDownList runat="server" ID="subcomponentDDL" DataTextField="Name" DataValueField="subcomponentPK" CssClass="form-control SubmitEnabler"/>
<small class="form-text text-muted">
Description of subcomponent.
</small>
</div>
</div>
... Other page elements ...
</div>
</ContentTemplate>
</asp:UpdatePanel>
但是,如果数据库在用户加载所述页面后更新,则该页面显示不再是最新的项目列表,从而允许用户选择并推送可能不再可用的项目,或者不显示全部目前有货。
我试图在用户打开 DDL 时但在渲染之前使 DDL 更新其项目列表,理论上有效地使 DDL 在 DDL 的每个打开事件上进行数据库查询。
然而问题就在这里;我无法找到任何本机方法来检测此类事件或检测 DDL 的打开,更不用说触发数据库查询更新的函数了。
我已经尝试过使用自定义 JavaScript 函数来实现此类事件检测,但我所能实现的最多的是 OnFocus 更新,但它会触发(顾名思义)基本上与 DDL 的任何交互。
请问这里有人有什么建议或建议吗?我花了很多时间研究这个问题,但没有找到任何相关或类似的问题/辩论。
既然 ddl 位于更新面板内,那么为什么不使用自动回发,当用户做出选择时,您可以检查选择是否存在,同时重新加载 dll。
并且由于 dll 位于更新面板内,因此不会发生或似乎发生了整页回发。
因此,您可以在选择组合框时检查选择是否存在,如果不存在,则可以采取行动,不允许选择,并重新加载 ddl。
所以,说出这个标记:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<h3>Select Hotel</h3>
<asp:DropDownList ID="cboHotels" runat="server"
DataValueField="ID"
DataTextField="HotelName"
AutoPostBack="true"
OnSelectedIndexChanged="cboHotels_SelectedIndexChanged"
>
</asp:DropDownList>
<br />
<asp:Label ID="lblError" runat="server" Text="" ForeColor="Red"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
背后的代码可以是这样的:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadData();
}
void LoadData()
{
String strSQL =
@"SELECT ID, HotelName FROM tblHotelsA
WHERE Active = 1
ORDER BY HotelName";
cboHotels.DataSource = General.MyRst(strSQL);
cboHotels.DataBind();
cboHotels.Items.Insert(0, new ListItem("Please Select Hotel", ""));
}
protected void cboHotels_SelectedIndexChanged(object sender, EventArgs e)
{
int HotelPK = 0;
if (cboHotels.SelectedIndex > 0)
{
HotelPK = int.Parse(cboHotels.SelectedItem.Value);
// make sure this selection exists
string strSQL =
@"SELECT ID, HotelName FROM tblHotelsA
WHERE ID = @ID AND Active = 1";
SqlCommand cmdSQL = new SqlCommand(strSQL);
cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = HotelPK;
DataTable dtCheck = General.MyRstP(cmdSQL);
if (dtCheck.Rows.Count == 0)
{
// selection no longer exists, zero out HotelPK
HotelPK = 0;
cboHotels.Items.Clear();
lblError.Text = "Selection no longer available, please select again";
}
else
{
lblError.Text = "";
}
LoadData(); // re-load and refresh cbo box
if (HotelPK != 0)
{
// cbo was re-loaded, so set cbo to user selection,
// along with any new items, and deleted items removed
cboHotels.Text = HotelPK.ToString();
}
}
}
那么,如果用户尝试选择列表中不存在的项目呢?
然后他们就会得到/看到这个效果:
因此,我让页面加载,然后将其中一项标记为 Active = false。
出现这种情况:
但是,如果用户选择一个有效值,去喝咖啡,然后回来并点击提交,会发生什么?
嗯,这意味着您的提交按钮还必须检查有效的选择,并且代码将与我在 SelectedIndexChanged 事件中的代码非常相同。
如上所述,另一种方法是采用“网络套接字”和组合框的实时更新。这些所谓的“推送”通知基于使用网络套接字。这也是在线“聊天”系统的工作原理,当每个用户键入时,网页就会实时更新。然而,设置一个 Web 套接字可能需要相当多的工作,因此大多数人采用“预制”框架,例如 SignalR。
您可以在这里阅读有关 SignalR 的信息:
https://dotnet.microsoft.com/en-us/apps/aspnet/signalr
但是,我认为采用 SignalR 来解决此类问题有点矫枉过正,在选择时对 ddl 进行简单检查,以及提交时的 ddl 无论如何都可以很好地涵盖此类场景。