Создайте экземпляр UserControl в обработчике ASHX, где ASCX зависит от родительского ASPX - PullRequest
0 голосов
/ 11 февраля 2010

Я нашел эту чрезвычайно полезную статью о создании экземпляров пользовательских контролей ASP.NET в обработчиках .ASHX с помощью Скотта Гатри .

К сожалению, теперь у меня есть требование, когда мне нужно создать экземпляр UserControl, который зависит от родительской страницы. В этом случае я не могу использовать тот же метод для создания UserControl.

Кто-нибудь может подсказать, как мне поступить? Что входит в создание экземпляра родительской страницы и последующее получение содержимого UserControl, который он содержит?

Просто для справки и, в частности, для определения типа зависимости, с которой я имею дело, UserControl - это панель, которая существует на главной странице Factsheet. В зависимости от предпочтений конфигурации пользователя различные элементы управления динамически генерируются в базовом классе Factsheet FactsheetBuilderPage и включаются на страницу.

UserControl имеет свойства, такие как:

public DateTime EffectiveDate
{
    get
    {
        return ((FactsheetBuilderPage)this.Page).EffectiveDate;
    }
}

public Site ConfiguredSite
{
    get { return ((FactsheetBuilderPage)this.Page).SiteConfiguration; }
}

public ConfiguredFund Fund
{
    get
    {
        return ((FactsheetBuilderPage)this.Page).Fund;
    }
}

, которые ссылаются на класс FactsheetBuilderPage, что означает, что мне нужно создать класс FactsheetBuilderPage для ссылки на него.

В идеале я мог бы решить эту проблему без необходимости изменять существующую кодовую базу, потому что рефакторинг это будет настоящей болью !!

Спасибо, ребята

Dave

Ответы [ 3 ]

3 голосов
/ 11 февраля 2010

Боюсь, вы вошли в этот. Если вы собираетесь создать пользовательский элемент управления, который зависит от его страницы, то почему он разделен? Пользовательский элемент управления используется для создания модульности. Они не должны зависеть от страницы.

Тем не менее, что такое зависимость? Поскольку вам, очевидно, не нужна страница, возможно, вы сможете предоставить то, что нужно, без страницы.

1 голос
/ 12 февраля 2010

Хорошо, так что решение оказалось изменить свойства UserControl на автоматические, а не просто получить геттер, который ссылается на родительскую страницу.

public ConfiguredFund Fund { get; set; }

public DateTime EffectiveDate { get; set; }

public Site ConfiguredSite { get; set; }

Теперь это означает, что я должен явно присваивать значения этим свойствам при создании экземпляра пользовательского элемента управления. Это позволяет мне создавать экземпляр этого UserControl в любом месте без необходимости родительской страницы, если я могу предоставить необходимые данные.

затем в моем обработчике создайте экземпляр UserControl и назначьте необходимые свойства:

private MyUserControl GetUserControl(int id)
{
    MyUserControl myUc = GetUserControl("Controls/MyUserControl.ascx");

    myUc.Fund = new ConfiguredFund(id);
    myUc.EffectiveDate = DateTime.Now;
    myUc.ConfiguredSite = siteManager.GetSiteById(2);

    return myUc;
}

Затем, чтобы получить рендеринг HTML, я использую слегка модифицированную версию кода Скотта Гатри:

public static string RenderView(MyUserControl viewControl, object data)
{
    Page pageHolder = new Page();

    if (data != null)
    {
        Type viewControlType = viewControl.GetType();
        FieldInfo field = viewControlType.GetField("Data");

        if (field != null)
        {
            field.SetValue(viewControl, data);
        }
        else
        {
            throw new Exception("View file doesn't have a public Data property");
        }
    }

    pageHolder.Controls.Add(viewControl);

    StringWriter output = new StringWriter();
    HttpContext.Current.Server.Execute(pageHolder, output, false);

    return output.ToString();
}

Спасибо, ребята

Dave

0 голосов
/ 11 февраля 2010

Вы можете создать и выполнить страницу несколькими способами. Одним из них является использование класса BuildManager для создания экземпляра страницы, например:

Page page = BuildManager.CreateInstanceFromVirtualPath ("/ my / app / page.aspx", typeof (MyPageClass)) как Page;

Но если вам нужно, чтобы ваша страница выполнялась в текущем контексте запроса, попробуйте это так:

Page page = new MyPageClass();  
page.AppRelativeVirtualPath = 
         context.Request.AppRelativeCurrentExecutionFilePath; 
page.ProcessRequest(context);

Это, конечно, благодаря Рику Стролю .

...