代码之家  ›  专栏  ›  技术社区  ›  Andy West

如何根据属性值更新设计时用户控件接口?

  •  5
  • Andy West  · 技术社区  · 15 年前

    我创建了一个具有以下公共属性的用户控件:

    [Browsable(true)]
    public string Text
    {
        get { return pnlLookupTable.GroupingText; }
        set { pnlLookupTable.GroupingText = value; }
    }
    

    如您所料,pnllookuptable是一个面板控件。我可以在“属性”窗口中更改文本属性的值,它会像应该的那样反映在标记中。但是,页面内用户控件的设计视图不显示面板的更新的GroupingText。我怎样才能做到这一点?

    编辑 :

    根据请求,这里是该属性所属的整个类。你可以看到没有什么特别的事情发生:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    public partial class LookupTable : System.Web.UI.UserControl
    {
        [Browsable(true)]
        public string Text
        {
            get { return pnlLookupTable.GroupingText; }
            set { pnlLookupTable.GroupingText = value; }
        }
    }
    

    以下是.ascx文件的相关部分:

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="LookupTable.ascx.cs" Inherits="LookupTable" %>
    <asp:Panel ID="pnlLookupTable" runat="server" GroupingText="Lookup Table">
        <%-- Irrelevant content here. --%>
    </asp:Panel>
    

    为了保护代码的专有性,我修改了一些标识符和其他一些琐碎的东西。

    我还应该重申,我正在查看添加了控件的设计模式下的Web窗体,并且正在更改文本属性。我想在设计器中看到对面板GroupingText的更改。

    2 回复  |  直到 15 年前
        1
  •  6
  •   Eilon    15 年前

    我得回想一下UserControlDesigner代码…

    短篇小说:我认为这是不可能的。

    长话短说:

    据我所知,位于ascx文件中的用户控件永远不会在设计器中运行。也就是说,在Visual Studio中,不会编译或运行ascx或ascx.cs文件中的代码。这是为了防止由于无法在CLR中卸载已加载的程序集而导致的内存泄漏。为了在用户控件中运行代码,Visual Studio必须将ascx编译成一个dll,然后加载它,然后运行代码。每次更改ascx时,它都必须再次执行此操作。每次执行此操作时,从您的ascx生成的额外加载的dll将消耗更多的内存。

    由于clr中的这种限制,用户控件设计器实际上不编译或运行ascx文件。相反,它解析ascx文件并在其中查找控件,并加载这些控件。对于在ascx文件中找到的每个控件,它将创建关联的控件设计器并呈现该控件的设计时HTML。

    有几种方法可以解决这个问题:

    1. 您可以编写一个从控件派生的常规自定义控件,而不是使用ascx用户控件,代码将写入一个cs或vb文件中。
    2. 将ascx编译成一个dll。大卫·埃博写了一篇 blog post 关于如何做到这一点。

    这两个解决方案应该工作的原因是它们都涉及将代码编译成一个DLL。其想法是,DLL不会经常更改,因此Visual Studio可以安全地加载DLL,而无需在每次DLL更改(以及内存泄漏)时都重新加载它。

        2
  •  1
  •   womp    15 年前

    我想我一定有答案,把它写了出来,但有什么事情困扰着我,所以我测试了几个小时。

    结果(就像艾伦说的那样),我觉得你做不到。

    ascx控件完全忽略 DesignerAttribute ,因此不能为它们指定自定义的设计时渲染器。我想“好吧,我可以对面板控件进行子类化,并在其上指定一个新的设计器,该设计器将从父控件获取属性”。你猜怎么着?没有机会。如果在设计器中访问面板的父控件, 它不会强制转换为自定义用户控件类型 .我可以看到它是一个用户控件,它不可能是除我的testUserControl之外的任何其他用户控件,但是如果我尝试强制转换它,设计器类会抛出一个异常!

    老实说,这让我心烦意乱。这基本上就是Eilon所说的——在设计模式下对Web用户控件有一个有意的限制。

    Here's a vague post from Steven Cheng suggesting that design time support is just a no-go for web usercontrols.

    虽然这对我来说是一个有趣的学习机会,但我很抱歉地报告说,我不认为.ascx会切断它。我敢肯定,即使像艾伦建议的那样把它编译成一个dll,也做不到。您可能需要走自定义控制路线。