Это займет немного времени, чтобы объяснить, но здесь это идет:
1) Я создал страницу .aspx с элементом управления PlaceHolder.
2) Я использую страницу для загрузки «контейнера» UserControl из БД:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
try
{
Utility.MenuItem menuItem = CurrentMenuHandler.ByCurrentPath();
var clientId = CurrentClient.ID;
var userId = CurrentUser.ID;
if (menuItem.UserControlPath.Length > 0)
{
UserControl control = base.LoadControl(menuItem.UserControlPath, 2, clientId, userId, menuItem.ID);
plContainerControl.Controls.Add(control);
}
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}
3) В элементе управления контейнером я использую сеточное представление DevExpress для динамической загрузки пользовательских элементов управления, когда GridView переходит в режим «Редактирование».
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//grab business objects from Factory
gridBusObj = Utility.GridItemBF.GetBusObject(base.ClientId, productCode);
coreBusObj = Utility.CoreBF.GetBusObject();
//load the data from the database into objects
LoadData();
PopulateColumns();
grid.SettingsEditing.Mode = GridViewEditingMode.PopupEditForm;
grid.HtmlRowCreated += GridHtmlRowCreated;
grid.HtmlEditFormCreated+= GridHtmlEditFormCreated;
grid.Templates.EditForm = new EditFormTemplate(ApplicationId, ClientId, UserId, MenuId, Page, gridColumns, cores);
grid.SettingsEditing.PopupEditFormModal = true;
BindGrid();
}
public class EditFormTemplate : ITemplate
{
public IList<IGridable> GridColumns { get; set; }
private int ApplicationId { get; set; }
private int ClientId { get; set; }
private int UserId { get; set; }
private int MenuItemId { get; set; }
private Page CurrentPage { get; set; }
private IList<Core> Cores;
public EditFormTemplate(int applicationId, int clientId, int userId, int menuItemId, Page currentPage, IList<IGridable> gridColumns, IList<Core> cores)
{
GridColumns = gridColumns;
ApplicationId = applicationId;
ClientId = clientId;
UserId = userId;
MenuItemId = menuItemId;
CurrentPage = currentPage;
Cores = cores;
}
#region ITemplate Members
public void InstantiateIn(Control container)
{
var formContainer = new System.Web.UI.WebControls.Panel {CssClass = "form-container"};
var coreColumn = new HtmlGenericControl("div");
var coreFilter = new HtmlGenericControl("div");
var title = new HtmlGenericControl("h2") {InnerHtml = "Core Name"};
coreColumn.Attributes.Add("class", "filter-column");
coreFilter.Attributes.Add("class", "filter");
var gridContainer = (GridViewEditFormTemplateContainer)container;
var coreId = (int) gridContainer.KeyValue;
var core = (Cores.Where(c => c.CoreId == coreId)).First();
var txtCoreName = new System.Web.UI.WebControls.TextBox {ID = "txtCoreName", Text = core.CoreName};
coreFilter.Controls.Add(title);
coreFilter.Controls.Add(txtCoreName);
coreColumn.Controls.Add(coreFilter);
formContainer.Controls.Add(coreColumn);
formContainer.Controls.Add(new LiteralControl(@"<div class=""clearfix""> </div>"));
for (int index = 0; index < GridColumns.Count; index++)
{
IGridable gridItem = GridColumns[index];
IGridable lastGridItem = GridColumns[index == 0 ? index : index - 1];
if (gridItem is GridParameter)
{
UserControl childControlTemplate = LoadControl(gridItem.UserControlPath, ApplicationId, ClientId,
UserId, MenuItemId, gridItem);
childControlTemplate.ID = gridItem.ParamName;
var lastRowIndex = Math.Floor((Decimal)((Decimal)lastGridItem.SortOrder / (Decimal)10.0));
var currentRowIndex = Math.Floor((Decimal) ((Decimal) gridItem.SortOrder/(Decimal) 10.0));
if (lastRowIndex < currentRowIndex )
formContainer.Controls.Add(new LiteralControl(@"<div class=""clearfix""> </div>"));
formContainer.Controls.Add(childControlTemplate);
}
}
var updateLink = new ASPxGridViewTemplateReplacement
{
ReplacementType = GridViewTemplateReplacementType.EditFormUpdateButton
};
var cancelLink = new ASPxGridViewTemplateReplacement
{
ReplacementType = GridViewTemplateReplacementType.EditFormCancelButton
};
formContainer.Controls.Add(new LiteralControl(@"<div class=""clearfix""> </div>"));
var actionsContainer = new HtmlGenericControl("div");
actionsContainer.Attributes.Add("class","edit-actions");
actionsContainer.Controls.Add(updateLink);
actionsContainer.Controls.Add(cancelLink);
formContainer.Controls.Add(actionsContainer);
formContainer.Controls.Add(new LiteralControl(@"<div class=""clearfix""> </div>"));
container.Controls.Add(formContainer);
}
#endregion
private UserControl LoadControl(string userControlPath, params object[] constructorParameters)
{
var ctl = CurrentPage.LoadControl(userControlPath) as UserControl;
// Find the relevant constructor
if (ctl != null)
{
var constructor = ctl.GetType().BaseType.GetConstructor(constructorParameters.Select(constParam => constParam.GetType()).ToArray());
//And then call the relevant constructor
if (constructor == null)
{
throw new MemberAccessException("The requested constructor was not found on : " + ctl.GetType().BaseType.ToString());
}
else
{
constructor.Invoke(ctl, constructorParameters);
}
}
// Finally return the fully initialized UC
return ctl;
}
}
4) Затем элемент управления «контейнер» загружает свой UserControl ListBox (Postback) и вот как это реализовано:
public ListBox(int applicationId, int clientId, int userId, int menuItemId, Objects.IGridable gridItem)
: base(applicationId, clientId, userId, menuItemId)
{
GridItem = gridItem;
}
private Objects.IGridable GridItem;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
lstContainer.SelectedIndexChanged += new EventHandler(lstDimension_SelectedIndexChanged);
lstContainer.DataSource = GridItem.ParameterValues;
lstContainer.DataTextField = "ValueName";
lstContainer.AppendDataBoundItems = true;
lstContainer.DataBind();
lblContainer.Text = GridItem.ColumnName;
}
5) Затем я создал интерфейс, который реализован во всех моих пользовательских элементах управления обратной передачей:
public interface IParameter
{
IGridable ClientParameter { get; set; }
}
6) и вот реализация этого интерфейса:
#region IParameter Members
public IGridable ClientParameter
{
get
{
foreach (ParameterValue parameterValue in GridItem.ParameterValues)
{
parameterValue.isSelected = false;
foreach (string selectedValue in lstDimension.GetSelectedValues())
{
if (parameterValue.ValueName == selectedValue)
{
parameterValue.isSelected = true;
}
}
}
return GridItem;
}
set
{
ClientParameter = value;
}
}
#endregion
7) В контроле контейнера, когда я иду, чтобы получить выбранные значения из списка (или ClientParameter), это то, где я сталкиваюсь с проблемами при извлечении фактических выбранных значений из списка
foreach (IGridable gridColumnTemplate in gridColumns)
{
var myControl = grid.FindEditFormTemplateControl(gridColumnTemplate.ParamName);
if (myControl is IParameter)
{
var clientControl = (IParameter)myControl;
gridColumnTemplate.ParameterValues = clientControl.ClientParameter.ParameterValues;
var parameter = parameterListElement.AppendChild(parameterXml.CreateElement("Parameter"));
var parameterName = parameterXml.CreateAttribute("ParameterName");
parameterName.Value = gridColumnTemplate.ParamName;
parameter.Attributes.Append(parameterName);
foreach (ParameterValue paramValue in clientControl.ClientParameter.ParameterValues)
{
if (paramValue.isSelected)
{
XmlNode value = parameter.AppendChild(parameterXml.CreateElement("pv"));
value.InnerXml = paramValue.ValueId;
}
}
}
}