如果 Else 不将 gridview 更改为在 selectedindexchanged 上可见 c#
If Else does not change gridviews to visible on selectindexchanged c#
这很简单,当用户 select 一行时,它应该从面板 1 或面板 2 中的两个 table 中的任何一个中调出相关行。我的问题是,当我 select 一行只有一个 table 有内容时,它工作正常,显示 table 及其关联的 Maintenance_ID,我去 select 另一行,其中两个 table 都有关联的 Maintenance_ID,它只显示之前已经显示的 table 的内容。
当我放置一个断点时,我注意到另一个 table 的 Rows.Count 等于 0,但是当我 运行 程序结束并且 select 一行在两个 table 都有内容的地方,它会显示两个 table 应该显示的内容。当我转到 select 另一行只有一个 table 的内容时,它仍然显示两个 table,只是它显示 table 没有相关的 Maintenance_ID 为空。
很明显我在语法上做错了什么,但我不确定是什么,欢迎提出建议。
编辑:这是我的数据绑定事件和新的 SelectedIndexChanged 代码,但现在什么都没有发生:
protected void MaintenanceTable_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow r = MaintenanceTable.Rows[MaintenanceTable.SelectedIndex];
string mid = r.Cells[2].Text;
lpDataSource.SelectParameters["mid"].DefaultValue = mid;
lpDataSource.DataBind();
wsDataSource.SelectParameters["mid"].DefaultValue = mid;
wsDataSource.DataBind();
}
protected void lpTable_DataBound(object sender, EventArgs e)
{
if (lpTable.Rows.Count > 0)
{
lpTableLabel.Visible = true;
Panel1.Visible = true;
}
else
{
lpTableLabel.Visible = false;
Panel1.Visible = false;
}
}
protected void GridView1_DataBound(object sender, EventArgs e)
{
if (GridView1.Rows.Count > 0)
{
wsTableLabel.Visible = true;
Panel2.Visible = true;
}
else
{
wsTableLabel.Visible = false;
Panel2.Visible = false;
}
}
编辑:关联的 GridView 和数据源:
<asp:GridView ID="MaintenanceTable" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="Maintenance_ID" DataSourceID="MaintDataSource" EmptyDataText="There are no data records to display." BackColor="White" BorderColor="#999999" BorderStyle="None" BorderWidth="1px" CellPadding="3" GridLines="Vertical" Width="1000px" OnRowDeleted="MaintenanceTable_RowDeleted" OnSelectedIndexChanged="MaintenanceTable_SelectedIndexChanged" ShowFooter="True">
<asp:SqlDataSource ID="MaintDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:itassetmgmtConnectionString1 %>" SelectCommand="SELECT * FROM [Maintenance]" >
<asp:GridView ID="lpTable" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" DataSourceID="lpDataSource" EmptyDataText="There are no data records to display." BackColor="White" BorderColor="#999999" BorderStyle="None" BorderWidth="1px" CellPadding="3" GridLines="Vertical" DataKeyNames="Laptop_ID" Height="39px" Width="1427px" OnDataBound="lpTable_DataBound" >
<asp:SqlDataSource ID="lpDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:itassetmgmtConnectionString1 %>" SelectCommand="SELECT * FROM [Laptops] WHERE [Maintenance_ID]=@mid" ConflictDetection="CompareAllValues">
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" DataSourceID="wsDataSource" EmptyDataText="There are no data records to display." BackColor="White" BorderColor="#999999" BorderStyle="None" BorderWidth="1px" CellPadding="3" GridLines="Vertical" DataKeyNames="Workstation_ID" Height="39px" OnDataBound="GridView1_DataBound" >
<asp:SqlDataSource ID="wsDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:itassetmgmtConnectionString1 %>" SelectCommand="SELECT * FROM [Workstations] WHERE [Maintenance_ID]=@mid" ConflictDetection="CompareAllValues">
你做错了。除了基于 selected 行的 selected 字段外,您的查询字符串没有变化。这告诉我几件事:
- 与此代码关联的字段:
r.Cells[2].Text
应该是 MaintenanceTable
的 DataKey
- 每个其他 tables (lp, ws) 都有自己的数据源,因为您正在设置
Select
并强制 Databind()
但没有分配数据源,这让我相信你已经设置了他们的 DataSourceID
(你应该这样做)
- 从属 table 上的 Databind 事件没有发生,因为您在玩弄父控件的可见性。这是因为 Page Lifecycle 中事物的顺序。当您在
MaintenanceTable_SelectedIndexChanged
事件中将控件的可见性设置为 false 时,永远不会引发 Panel
及其相关子控件的 Databind
事件。这就是为什么你的能见度问题总是落后一步。
那么你应该怎么做:
- 注释掉上面的现有代码。
- 添加与
r.Cells[2].Text
关联的字段作为 MaintenanceTable
的 DataKey
- 将 select 语句添加到每个依赖的 DataSources 但已修改
接受参数而不是将参数作为字符串附加。
- 向引用
MaintenanceTable
的 SelectedValue 的每个相关 Tables DataSources 添加一个 ControlParameter
- 面板可见性需要在 Databind 发生后设置,因此请在
Page_PreRenderComplete
事件中设置,甚至更好,在各自依赖的 table 的 DataBound
事件中设置。
编辑:一般来说,您试图在 SelectedIndexChanged 事件中控制太多太早。通常我更喜欢在事件期间通过 Class 成员变量设置状态变量,如果它们只需要在给定的生命周期内存在,或者如果它们需要持久化,则在 ViewState 或 Session 中。然后让控件通过在必要时在各自的事件中访问这些状态变量来对自己进行排序。
附录
这就是生成一个网页所需的全部内容,该网页根据 Main Table 中的行 selection 填充相关的 tables。绝对不需要隐藏代码。
<asp:GridView ID="gvMaintenanceTable" runat="server" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1" DataKeyNames="case_id">
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="caption" HeaderText="caption" SortExpression="caption"></asp:BoundField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString='<%$ ConnectionStrings:SomeConnectionString %>'
SelectCommand="SELECT top 10 caption, case_id FROM tbl_case_info">
</asp:SqlDataSource>
<asp:Panel ID="Panel1" runat="server">
<asp:GridView ID="lpTable" runat="server" AutoGenerateColumns="False"
DataSourceID="lpDataSource"
DataKeyNames="invoice_id">
<Columns>
<asp:BoundField DataField="invoice_number" HeaderText="invoice_number" SortExpression="invoice_number"></asp:BoundField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="lpDataSource" runat="server" ConnectionString='<%$ ConnectionStrings:SomeConnectionString %>'
SelectCommand="SELECT invoice_number, invoice_id FROM tbl_invoice WHERE (case_id = @CaseID)">
<SelectParameters>
<asp:ControlParameter Name="CaseID"
ControlID="gvMaintenanceTable"
PropertyName="SelectedValue"></asp:ControlParameter>
</SelectParameters>
</asp:SqlDataSource>
</asp:Panel>
<asp:Panel ID="Panel2" runat="server">
<asp:GridView ID="wsTable" runat="server" DataSourceID="wsDataSource" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="caption" HeaderText="caption" SortExpression="caption"></asp:BoundField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="wsDataSource" runat="server" ConnectionString='<%$ ConnectionStrings:SomeConnectionString %>'
SelectCommand="SELECT caption, user_id, case_id FROM tbl_case_info WHERE (case_id = @CaseID)">
<SelectParameters>
<asp:ControlParameter Name="CaseID"
ControlID="gvMaintenanceTable"
PropertyName="SelectedValue"></asp:ControlParameter>
</SelectParameters>
</asp:SqlDataSource>
</asp:Panel>
这是可见性的隐藏代码(请原谅 VB),假设标签出现在面板内。如果标签与 table
关联,请考虑使用 Gridview Caption
属性 而不是 <asp:Label>
Private Sub lpTable_DataBound(sender As Object, e As EventArgs) Handles lpTable.DataBound
Panel1.Visible = (lpTable.Rows.Count > 0)
End Sub
Private Sub wsTable_DataBound(sender As Object, e As EventArgs) Handles wsTable.DataBound
Panel2.Visible = (wsTable.Rows.Count > 0)
End Sub
编辑:确保 Panel
将它们的 Visibility
属性 重置为 True
否则,一旦为假,它们包含的 Gridview
将永远不会 Databind
在主要 table.
的后续行 select 离子上
Private Sub Panel1_Load(sender As Object, e As EventArgs) Handles Panel1.Load
Panel1.Visible = True
End Sub
Private Sub Panel2_Load(sender As Object, e As EventArgs) Handles Panel2.Load
Panel2.Visible = True
End Sub
这很简单,当用户 select 一行时,它应该从面板 1 或面板 2 中的两个 table 中的任何一个中调出相关行。我的问题是,当我 select 一行只有一个 table 有内容时,它工作正常,显示 table 及其关联的 Maintenance_ID,我去 select 另一行,其中两个 table 都有关联的 Maintenance_ID,它只显示之前已经显示的 table 的内容。
当我放置一个断点时,我注意到另一个 table 的 Rows.Count 等于 0,但是当我 运行 程序结束并且 select 一行在两个 table 都有内容的地方,它会显示两个 table 应该显示的内容。当我转到 select 另一行只有一个 table 的内容时,它仍然显示两个 table,只是它显示 table 没有相关的 Maintenance_ID 为空。
很明显我在语法上做错了什么,但我不确定是什么,欢迎提出建议。
编辑:这是我的数据绑定事件和新的 SelectedIndexChanged 代码,但现在什么都没有发生:
protected void MaintenanceTable_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow r = MaintenanceTable.Rows[MaintenanceTable.SelectedIndex];
string mid = r.Cells[2].Text;
lpDataSource.SelectParameters["mid"].DefaultValue = mid;
lpDataSource.DataBind();
wsDataSource.SelectParameters["mid"].DefaultValue = mid;
wsDataSource.DataBind();
}
protected void lpTable_DataBound(object sender, EventArgs e)
{
if (lpTable.Rows.Count > 0)
{
lpTableLabel.Visible = true;
Panel1.Visible = true;
}
else
{
lpTableLabel.Visible = false;
Panel1.Visible = false;
}
}
protected void GridView1_DataBound(object sender, EventArgs e)
{
if (GridView1.Rows.Count > 0)
{
wsTableLabel.Visible = true;
Panel2.Visible = true;
}
else
{
wsTableLabel.Visible = false;
Panel2.Visible = false;
}
}
编辑:关联的 GridView 和数据源:
<asp:GridView ID="MaintenanceTable" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="Maintenance_ID" DataSourceID="MaintDataSource" EmptyDataText="There are no data records to display." BackColor="White" BorderColor="#999999" BorderStyle="None" BorderWidth="1px" CellPadding="3" GridLines="Vertical" Width="1000px" OnRowDeleted="MaintenanceTable_RowDeleted" OnSelectedIndexChanged="MaintenanceTable_SelectedIndexChanged" ShowFooter="True">
<asp:SqlDataSource ID="MaintDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:itassetmgmtConnectionString1 %>" SelectCommand="SELECT * FROM [Maintenance]" >
<asp:GridView ID="lpTable" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" DataSourceID="lpDataSource" EmptyDataText="There are no data records to display." BackColor="White" BorderColor="#999999" BorderStyle="None" BorderWidth="1px" CellPadding="3" GridLines="Vertical" DataKeyNames="Laptop_ID" Height="39px" Width="1427px" OnDataBound="lpTable_DataBound" >
<asp:SqlDataSource ID="lpDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:itassetmgmtConnectionString1 %>" SelectCommand="SELECT * FROM [Laptops] WHERE [Maintenance_ID]=@mid" ConflictDetection="CompareAllValues">
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" DataSourceID="wsDataSource" EmptyDataText="There are no data records to display." BackColor="White" BorderColor="#999999" BorderStyle="None" BorderWidth="1px" CellPadding="3" GridLines="Vertical" DataKeyNames="Workstation_ID" Height="39px" OnDataBound="GridView1_DataBound" >
<asp:SqlDataSource ID="wsDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:itassetmgmtConnectionString1 %>" SelectCommand="SELECT * FROM [Workstations] WHERE [Maintenance_ID]=@mid" ConflictDetection="CompareAllValues">
你做错了。除了基于 selected 行的 selected 字段外,您的查询字符串没有变化。这告诉我几件事:
- 与此代码关联的字段:
r.Cells[2].Text
应该是MaintenanceTable
的 DataKey
- 每个其他 tables (lp, ws) 都有自己的数据源,因为您正在设置
Select
并强制Databind()
但没有分配数据源,这让我相信你已经设置了他们的DataSourceID
(你应该这样做) - 从属 table 上的 Databind 事件没有发生,因为您在玩弄父控件的可见性。这是因为 Page Lifecycle 中事物的顺序。当您在
MaintenanceTable_SelectedIndexChanged
事件中将控件的可见性设置为 false 时,永远不会引发Panel
及其相关子控件的Databind
事件。这就是为什么你的能见度问题总是落后一步。
那么你应该怎么做:
- 注释掉上面的现有代码。
- 添加与
r.Cells[2].Text
关联的字段作为MaintenanceTable
的 DataKey
- 将 select 语句添加到每个依赖的 DataSources 但已修改
接受参数而不是将参数作为字符串附加。 - 向引用
MaintenanceTable
的 SelectedValue 的每个相关 Tables DataSources 添加一个 ControlParameter
- 面板可见性需要在 Databind 发生后设置,因此请在
Page_PreRenderComplete
事件中设置,甚至更好,在各自依赖的 table 的DataBound
事件中设置。
编辑:一般来说,您试图在 SelectedIndexChanged 事件中控制太多太早。通常我更喜欢在事件期间通过 Class 成员变量设置状态变量,如果它们只需要在给定的生命周期内存在,或者如果它们需要持久化,则在 ViewState 或 Session 中。然后让控件通过在必要时在各自的事件中访问这些状态变量来对自己进行排序。
附录
这就是生成一个网页所需的全部内容,该网页根据 Main Table 中的行 selection 填充相关的 tables。绝对不需要隐藏代码。
<asp:GridView ID="gvMaintenanceTable" runat="server" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1" DataKeyNames="case_id">
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="caption" HeaderText="caption" SortExpression="caption"></asp:BoundField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString='<%$ ConnectionStrings:SomeConnectionString %>'
SelectCommand="SELECT top 10 caption, case_id FROM tbl_case_info">
</asp:SqlDataSource>
<asp:Panel ID="Panel1" runat="server">
<asp:GridView ID="lpTable" runat="server" AutoGenerateColumns="False"
DataSourceID="lpDataSource"
DataKeyNames="invoice_id">
<Columns>
<asp:BoundField DataField="invoice_number" HeaderText="invoice_number" SortExpression="invoice_number"></asp:BoundField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="lpDataSource" runat="server" ConnectionString='<%$ ConnectionStrings:SomeConnectionString %>'
SelectCommand="SELECT invoice_number, invoice_id FROM tbl_invoice WHERE (case_id = @CaseID)">
<SelectParameters>
<asp:ControlParameter Name="CaseID"
ControlID="gvMaintenanceTable"
PropertyName="SelectedValue"></asp:ControlParameter>
</SelectParameters>
</asp:SqlDataSource>
</asp:Panel>
<asp:Panel ID="Panel2" runat="server">
<asp:GridView ID="wsTable" runat="server" DataSourceID="wsDataSource" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="caption" HeaderText="caption" SortExpression="caption"></asp:BoundField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="wsDataSource" runat="server" ConnectionString='<%$ ConnectionStrings:SomeConnectionString %>'
SelectCommand="SELECT caption, user_id, case_id FROM tbl_case_info WHERE (case_id = @CaseID)">
<SelectParameters>
<asp:ControlParameter Name="CaseID"
ControlID="gvMaintenanceTable"
PropertyName="SelectedValue"></asp:ControlParameter>
</SelectParameters>
</asp:SqlDataSource>
</asp:Panel>
这是可见性的隐藏代码(请原谅 VB),假设标签出现在面板内。如果标签与 table
关联,请考虑使用 GridviewCaption
属性 而不是 <asp:Label>
Private Sub lpTable_DataBound(sender As Object, e As EventArgs) Handles lpTable.DataBound
Panel1.Visible = (lpTable.Rows.Count > 0)
End Sub
Private Sub wsTable_DataBound(sender As Object, e As EventArgs) Handles wsTable.DataBound
Panel2.Visible = (wsTable.Rows.Count > 0)
End Sub
编辑:确保 Panel
将它们的 Visibility
属性 重置为 True
否则,一旦为假,它们包含的 Gridview
将永远不会 Databind
在主要 table.
Private Sub Panel1_Load(sender As Object, e As EventArgs) Handles Panel1.Load
Panel1.Visible = True
End Sub
Private Sub Panel2_Load(sender As Object, e As EventArgs) Handles Panel2.Load
Panel2.Visible = True
End Sub