У меня довольно странная проблема с моими пользовательскими элементами управления, с которыми я работаю. Я кодирую некоторые пользовательские элементы управления для использования в модуле DotNetNuke.
В основном у меня есть UserControl на моей странице, который содержит некоторые элементы управления, а затем есть Placeholder, где я загружаю UserControl, в котором размещен GridView.
В основном вот моя структура страницы
<asp:Panel runat="server" ID="pnlServiceType" Visible="false">
<uc:ServiceType runat="server" ID="ServiceType" />
</asp:Panel>
Внутри этого пользовательского элемента управления находятся некоторые элементы формы, а затем следующее:
<asp:PlaceHolder runat="server" ID="phServices" />
Затем к этому заполнителю добавляется пользовательский элемент управления, например:
<p class="header"><asp:Label runat="server" ID="lblServiceHeader" Font-Bold="true" /></p>
<asp:GridView runat="server" ID="gvServices" AlternatingRowStyle-BackColor="#eaeaea" BorderStyle="None" GridLines="None"
AutoGenerateColumns="false" CellPadding="6" Width="100%" EnableViewState="false" OnRowEditing="gvServices_RowEditing">
Когда пользователь выбирает что-то в DropDownList, я удаляю элементы управления из Placeholder и повторно добавляю только один UserControl для набора записей для любого типа, который они выбрали, вот так
_serviceID = e.Value;
//Clear the controls out of the placeholder
phServices.Controls.Clear();
//Reset the count of grids for the OnInit() method
Session["GridCount"] = 0;
if (e.Value != "NULL")
{
PopulateServicesGrid(_service.GetServicesByFormType(Convert.ToInt32(e.Value)));
}
else
{
PopulateServicesGrid(_service.GetServicesByClient(Convert.ToInt32(_client)));
}
И метод PopulateServicesGrid:
private void PopulateServicesGrid(List<NOAService> services)
{
//Creates a LINQ grouping based on the Billing Codes
//Allows a super easy creation of grids based on the grouped billing codes
var query = services.Select(service => service.BillingCode).Distinct();
foreach (string code in query)
{
var servicesByCode = services.Where(service => service.BillingCode == code).ToList();
ServicesGrid servicesGrid = LoadControl("~/DesktopModules/LEL Modules/NOA/ServicesGrid.ascx") as ServicesGrid;
Label lblServiceHeader = servicesGrid.FindControl("lblServiceHeader") as Label;
GridView gvServices = servicesGrid.FindControl("gvServices") as GridView;
phServices.Controls.Add(servicesGrid);
servicesGrid.ID = code;
lblServiceHeader.Text = servicesByCode[0].FormTypeName;
gvServices.DataSource = servicesByCode;
gvServices.DataBind();
Session["GridCount"] = phServices.Controls.Count;
}
}
И в моем UserControl ServiceType, в PageInit, я читаю пользовательский элемент управления ServiceGrid, чтобы мои сетки отображались при обратных передачах и не терялись из заполнителя.
void NOAServiceType_Init(object sender, EventArgs e)
{
for (int i = 0; i < Convert.ToInt32(Session["GridCount"]); i++)
{
ServicesGrid servicesGrid = LoadControl("~/DesktopModules/LEL Modules/NOA/ServicesGrid.ascx") as ServicesGrid;
phServices.Controls.Add(servicesGrid);
}
}
Сетки успешно заполняются, и все работает нормально. Но по какой-то причине в моем GridView у меня есть CommandField из
<asp:CommandField ShowEditButton="true" ItemStyle-HorizontalAlign="Right" EditText="Edit" UpdateText="Update"
EditImageUrl="~/images/LELModules/appbar.edit.rest.png" CancelImageUrl="~/images/LELModules/appbar.close.rest.png" UpdateImageUrl="~/images/LELModules/appbar.check.rest.png"
ButtonType="Image" CausesValidation="false" />
Когда я нажимаю команду «Редактировать» в строке «Сетка», ничего не происходит. Моя сетка не теряет ряды, управление осталось, вроде все должно быть ок. Событие RowEditing
не срабатывает, пока я не щелкну его второй раз.
Любая идея, почему это может происходить?
ОБНОВЛЕНИЕ: мне удалось выяснить, что мои обработчики SelectedIndexChanged эффективно сбрасывают DataSource
в сетке, содержащейся в UserControl, когда они считываются в PlaceHolder. Однако при нажатии CommandField (Edit) Init
срабатывает для UserControl, который содержит заполнитель
ServiceType UserControl < `Init` fires here
-Form elements
-Placeholder which holds
--UserControl with GridView
Метод Init
загружает новые экземпляры UserControl и добавляет их в PlaceHolder, но источником данных является null
. С EnableViewState=true
данные все еще привязаны, но если я обработаю PreRender
, я увижу, что DataSource
на моем gvServices | null
Можно ли вообще редактировать такие строки в GridView, который динамически добавляется в PlaceHolder снова и снова?
ИСПРАВЛЕНО Я узнал, в чем проблема, прочитав эту статью http://www.west-wind.com/weblog/posts/2006/Feb/24/Overriding-ClientID.-and-UniqueID-on-ASPNET-controls
Это заставило меня задуматься, а что, если идентификаторы менялись? Элементы управления вложены друг в друга. Поэтому я пошел и посмотрел на идентификатор GridView, ClientID и UniqueID, просто чтобы посмотреть. Когда элемент управления загружается в мой обработчик Init
, при добавлении ему присваивается суперобщий идентификатор.
private void PopulateServicesGrid(List<NOAService> services)
{
//Creates a LINQ grouping based on the Billing Codes
//Allows a super easy creation of grids based on the grouped billing codes
var query = services.Select(service => service.BillingCode).Distinct();
foreach (string code in query)
{
var servicesByCode = services.Where(service => service.BillingCode == code).ToList();
ServicesGrid servicesGrid = LoadControl("~/DesktopModules/LEL Modules/NOA/ServicesGrid.ascx") as ServicesGrid;
Label lblServiceHeader = servicesGrid.FindControl("lblServiceHeader") as Label;
GridView gvServices = servicesGrid.FindControl("gvServices") as GridView;
phServices.Controls.Add(servicesGrid);
**servicesGrid.ID = code;**
lblServiceHeader.Text = servicesByCode[0].FormTypeName;
gvServices.DataSource = servicesByCode;
gvServices.DataBind();
Session["GridCount"] = phServices.Controls.Count;
}
}
Я устанавливал идентификатор как что-то еще. Поэтому, когда я нажимал Edit RowCommand в своей сетке, он снова перезагружал элементы управления на Init
, и идентификаторы менялись обратно с моего кода пользовательского набора (T2020, извлеченный из моей базы данных) на общий идентификатор снова, это не знать, как запустить событие.
Я надеюсь, что это поможет кому-то, поскольку я потерял не менее 12 часов, решая эту проблему.