Ссылка на несуществующий пользовательский элемент управления?
Я создал приложение, которое ищет каталог и загружает все пользовательские элементы управления в форму, а затем использует метод "GetResult()", чтобы получить ответы из формы. Я не использовал этот стиль ООП, потому что я все еще учусь тому, как полностью использовать ООП, и сейчас я возвращаюсь к его разработке с ООП, чтобы перейти к следующей части, которая будет намного проще, если я буду работать с объектами. Прямо сейчас я создал свой класс RequestForm и хочу, чтобы RequestForm. Result достигал UC и вызывал метод GetResults(). Мне трудно заставить это сделать, хотя из-за недостатка знаний, возможно, кто-то может направить меня в правильном направлении.
FormUserControl - Абстрактный класс
namespace AccessRequest
{
public abstract class FormUserControl : UserControl
{
public abstract string Name();
public abstract string GetResults();
public abstract string EmailUsers();
}
}
RequestForm - класс объекта
namespace AccessRequest
{
public class RequestForm
{
public string Name { get; set; }
public string ControlID { get; set; }
public string StepName { get; set; }
public string FilePath { get; set; }
public string Results {
get
{
//How would I pull my usercontrol results with Control.GetReults() from within this area?
//I have since then turned this into a method. How would I get it to access my UserControl loaded on the asp page to grab the results?
}
set;
}
public string Emails { get; set; }
public int Position { get; set; }
public bool Visible { get; set; }
public RequestForm()
{
}
/// <summary>
/// FormResults gathers all needed information about the forms
/// </summary>
/// <param name="formName">Name of the Form</param>
/// <param name="formControlID">ID of the User Control </param>
/// <param name="wizardStepID">ID of the Wizard Step</param>
/// <param name="formFilePath">File path of the physical form</param>
/// <param name="formResults">Results from the form</param>
/// <param name="formEmails">Other emails to include</param>
public RequestForm(string formName, string formControlId, string wizardStepID, int wizardStepPosition, string formFilePath, string formResults, string formEmails)
{
this.Name = formName;
this.ControlID = formControlId;
this.StepName = wizardStepID;
this.Position = wizardStepPosition;
this.FilePath = formFilePath;
this.Results = formResults;
this.Emails = formEmails;
this.Visible = false;
}
public void SaveList(List<RequestForm> formList)
{
// HttpContext.Current.Session["FormList"] = formList;
}
}
}
Вот метод LoadForms(), который я вставил в OnInit для загрузки всех моих форм. Я не полностью реализовал часть RequestForm, но именно здесь я считаю, что она должна пойти для построения моего списка объектов.
private void LoadForms()
{
string dotColor = "Black";
string formColor = "#808080";
int loc = 3;
foreach (ListItem item in chklApplications.Items)
{
string formPath = (string)item.Value;
WizardStepBase newStep = new WizardStep();
newStep.ID = "wzStep" + item.Text;
newStep.Title = String.Format("<font color='{0}'> ¤</font> <font color='{1}'>{2} Request</font>", dotColor, formColor, item.Text);
var form = LoadControl(formPath);
form.ID = "uc" + item.Text;
newStep.Controls.Add(form);
wzAccessRequest.WizardSteps.AddAt(loc, newStep);
requestForm.Add(new RequestForm(
item.Text, //Form name
form.ID.ToString(), //User Control ID
newStep.ID.ToString(), //Wizardstep ID
loc, //Wizardstep Position
item.Value.ToString(), //File Path
null, //Form Results
null //Form Emails
));
loc++;
}
}
Здесь я устанавливаю, являются ли они видимыми или нет в боковом меню мастера управления. Кстати, кто-нибудь знает, как я могу предотвратить даже создание тегов таблицы для этого? Сейчас растёт большое пространство, куда я вставляю формы.
protected void SideBarList_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if (!ShowWizardStep(e.Item.DataItem))
{
e.Item.CssClass = "Hidden";
}
}
}
Спасибо за любой совет, который я получаю!:D
2 ответа
Хорошо, я понял это. У меня уже был метод, который собирал все результаты из формы и затем выплевывал их на экране проверки. Я манипулировал этим кодом так, что теперь он загружает их прямо в объект, с которым я работал. Теперь мои объекты заполнены всей динамической информацией, необходимой для управления, и я могу управлять ими намного проще. Вот код на случай, если кто-то еще ищет ответ.
Мои занятия
public class RequestForm
{
public string Name { get; set; }
public string ControlID { get; set; }
public string StepID { get; set; }
public string FilePath { get; set; }
public string Emails { get; set; }
public string Results { get; set; }
public int Position { get; set; }
public bool Visible { get; set; }
/// <summary>
/// FormResults gathers all needed information about the forms
/// </summary>
/// <param name="formName">Name of the Form</param>
/// <param name="formControlID">ID of the User Control </param>
/// <param name="wizardStepID">ID of the Wizard Step</param>
/// <param name="formFilePath">File path of the physical form</param>
/// <param name="formResults">Results from the form</param>
/// <param name="formEmails">Other emails to include</param>
public RequestForm(string formName, string formControlId, string wizardStepID, int wizardStepPosition, string formFilePath, string formEmails,string formResults, bool formVisible = false)
{
this.Name = formName;
this.ControlID = formControlId;
this.StepID = wizardStepID;
this.Position = wizardStepPosition;
this.FilePath = formFilePath;
this.Emails = formEmails;
this.Results = formResults;
this.Visible = formVisible;
}
}
Этот список содержит все элементы управления
public List<RequestForm> requestForm
{
get
{
List<RequestForm> requestList = new List<RequestForm>();
requestList = (List<RequestForm>)Session["RequestForms"];
var v = Session["RequestForms"];
return v != null ? (List<RequestForm>)v : null;
}
set
{
Session["RequestForms"] = value;
}
}
Это метод, который я использую, чтобы собрать результаты и затем поместить их в объект.
private void GatherFormsData()
{
if (requestForm != null)
{
foreach (RequestForm rform in requestForm)
{
if (rform.Visible)
{
WizardStepBase step = (WizardStep)wzAccessRequest.FindControl(rform.StepID);
FormUserControl form = (FormUserControl)step.FindControl(rform.ControlID);
rform.Results = String.Format("{0}<br>Email: {1}<br><br>", form.GetResults(), form.EmailContact());
}
}
}
}
Надеюсь, это кому-нибудь поможет.
Есть несколько проблем, которые вам нужно решить - и в вашем коде, и в ваших текущих знаниях:-) Начните с этого:
Прочтите несколько статей о жизненном цикле страниц ASP.NET, чтобы вы лучше узнали, что делать в каждом обработчике событий жизненного цикла (
OnInit
,OnLoad
…) Хорошей отправной точкой может быть этот обзор MSDN. Тем не менее, поищите в Google "жизненный цикл страницы ASP.NET", а также прочитайте несколько других статей и примеров.Кроме того, вам необходимо ознакомиться с характером обработки запросов ASP.NET. Вначале имейте в виду, что когда пользователь нажимает какую-то кнопку "Отправить", которая, в свою очередь, вызывает HTTP-запрос POST, вы несете ответственность за создание дерева элементов управления страницы, соответствующего его структуре, идентификаторам и т. Д., Как они были в предыдущий запрос. В противном случае ASP.NET не знает, как в какие элементы управления связывать данные, введенные пользователем.
Рядом с линией с меткой
//Lost and confused here :/
Вы создаете новый элемент управления и немедленно запрашиваете его для "результатов" (которые, как я ожидаю, будут значениями некоторых полей редактирования внутри него). Это не может работать, потому что, скорее всего, слишком рано для формы получать данные, полученные отPage
объект, который управляет обработкой запроса.Ваш
Results
собственность плохо спроектирована. Во-первых, вы не должны использовать свойства, которые фактически "генерируют" данные таким образом, что они могут изменяться без уведомления. Свойства должны использоваться как "умные поля", в противном случае вы получите менее управляемый и менее читаемый код. Во-вторых, сеттер, который вы оставили там как "set;", приводит к тому, что любое значение, присвоенное свойству, будет фактически потеряно, потому что нет способа его получить. Хотя в некоторых редких случаях такое поведение может быть преднамеренным, в вашем случае, я думаю, это просто ошибка.
Таким образом, хотя в настоящее время вы можете оставить любой "хороший ООП-подход" для решения своей проблемы, вы, безусловно, должны лучше ознакомиться с жизненным циклом страницы. Чтобы понять это, нужно немного подумать о принципах работы веб-приложений ASP.NET, но я уверен, что это даст вам тот толчок, который вам действительно нужен.
ОБНОВЛЕНИЕ: Что касается кода Тони (см. Комментарии), то для продвижения кода необходимо сделать следующее:
Список данных формы в
requestForm
свойство должно иметь кортеж из [путь ASCX формы, идентификатор элемента управления, фактическийRequestForm
класс данных]GatherForms
должен вызываться только при начальной загрузке страницы (т.е.if (Page.IsPostBack)
) и он должен заполнитьrequestForm
с соответствующими кортежами для доступных форм ASCX.И то и другое
chklApplications
и шаги мастера должны быть созданы вLoadForms
на основеrequestForm
содержание.Когда результаты должны быть собраны, идентификатор хранится в соответствующем
requestForm
запись может быть использована для поиска фактического пользовательского контроля.