使用RenderControl和ASP.NET菜单服务器控件的NullReferenceException

时间:2011-01-05 15:03:48

标签: c# .net asp.net

在调用ASP.NET菜单服务器控件的RenderControl方法时,我收到NullReferenceException异常。

我使用以下代码动态创建了控件:

private string RenderMenuHTML()
{
    StringBuilder sb = new StringBuilder();
    StringWriter sw = new StringWriter(sb);
    HtmlTextWriter hw = new HtmlTextWriter(sw);

    string menuXML = MenuManager.GetMenuXML();

    if (!string.IsNullOrEmpty(menuXML))
    {
        Menu menuControl = new UI.Menu();
        menuControl.ID = "menu";

        // Required properties to use RenderControl
        menuControl.SkipLinkText = string.Empty;
        menuControl.StaticPopOutImageUrl = "fake.gif";
        menuControl.ScrollUpImageUrl = "fake.gif";
        menuControl.ScrollDownImageUrl = "fake.gif";

        // Data binding
        XmlDataSource xmlDS = new XmlDataSource();
        xmlDS.ID = "xdsMenu";
        xmlDS.Data = menuXML;
        xmlDS.XPath = "MenuItems/MenuItem";

        // Menu data binding
        MenuItemBinding menuItemBinding = new MenuItemBinding();
        menuItemBinding.DataMember = "MenuItem";
        menuItemBinding.ValueField = "Value";
        menuItemBinding.TextField = "Text";
        menuItemBinding.ToolTipField = "Text";
        menuItemBinding.NavigateUrlField = "NavigateUrl";
        menuControl.DataBindings.Add(menuItemBinding);

        menuControl.DataSource = xmlDS;
        menuControl.DataBind();

        menuControl.RenderControl(hw); // <-- Problem here
    }

    return sb.ToString();
}

我需要做的是获取控件生成的HTML代码,这样我就不必手动生成它。我绑定了一个从递归菜单层次结构构建的XML数据源。

我已经查看了异常的详细信息,而调试器似乎没有说明任何内容。

当我将控件放在PlaceHolder中时,一切正常,但我需要的是HTML代码。

我似乎缺少Menu或MenuItem对象中的一些必需属性,但我在网上找不到任何依赖于此的内容。

有什么想法吗?

由于

5 个答案:

答案 0 :(得分:1)

我假设控件使用其上下文(例如它所在页面之类的东西)来做某事。虽然它不在页面上,但它无法访问此信息,这就是为什么它在占位符中工作而不在其外部。在调用rendercontrol方法之前,我建议将其添加到页面中的占位符。如果你想在之后从页面中删除它,那么没有什么可以阻止你这样做。我不确定是否可能存在副作用(例如,您可能需要注意ID的某些命名等,因为它们可能取决于您将其放在页面中的位置)。

我还会继续质疑你用这个HTML做什么?如果您在页面上使用它,为什么不只是将控件放在页面中并让它做它的事情?如果您在其他地方使用它,那么为什么不使用静态HTML?不是说你正在做的事情是错的,我只是在努力思考你在做什么,所以想要确保你一定想到你为什么这样做。 :)

答案 1 :(得分:1)

您可以使用init Event

初始化您的Control

这是初始化ASP页面上的Menu控件的示例

    protected void Menu1_Init(object sender, EventArgs e)
    {
        List<Category> categories = db.GetCategory();
        for (int i = 0; i < categories.Count; i++)
        {
            ((Menu)sender).Items.Add(new MenuItem(categories.ElementAt(i).Name));

        }
    } 

答案 2 :(得分:0)

我相信您需要覆盖Render或RenderChildren事件。

以下是Microsoft的一个示例

// Override default implementation to Render children according to needs. 
protected override void RenderChildren(HtmlTextWriter output)
{
   if (HasControls())
   {
      // Render Children in reverse order.
      for(int i = Controls.Count - 1; i >= 0; --i)
      {
         Controls[i].RenderControl(output);
      }
   }         
}

protected override void Render(HtmlTextWriter output)
{       
   output.Write("<br>Message from Control : " + Message);       
   output.Write("Showing Custom controls created in reverse" +
                                                    "order");         
   // Render Controls.
   RenderChildren(output);
}

这适用于标准ASPX页面:

protected override void Render(HtmlTextWriter writer) 
{
    StringBuilder sb = new StringBuilder();
    HtmlTextWriter htw = new HtmlTextWriter(new StringWriter(sb));
    base.Render(htw);
    writer.Write(sb.ToString());

    Logger.Write("TransferToColdFusion HTML: " + sb.ToString(), "Debug");
}

尝试此方法并传入菜单控件。

public string RenderControl(Control ctrl) 
{
    StringBuilder sb = new StringBuilder();
    StringWriter tw = new StringWriter(sb);
    HtmlTextWriter hw = new HtmlTextWriter(tw);

    ctrl.RenderControl(hw);
    return sb.ToString();
}

答案 3 :(得分:0)

看起来控件依赖于页面生命周期来初始化RenderControl中使用的某个变量。

您必须Debug the .NET Framework Source Code才能看到它是什么。

答案 4 :(得分:0)

我测试了你的代码并且它工作得很好...... hw在RenderControl方法之后有这个。

> <div id="menu">   <ul class="level1">
>       <li><a title="test" class="level1"
> href="www.google.com">test</a></li>
> 

</ul> </div>

The only difference was that I used a sample xml = @"<MenuItems><MenuItem Value='Test' Text='test' NavigateUrl='www.google.com'>Test</MenuItem></MenuItems>";

因此可能与您的Menu Xml源有关。