我使用以下公共属性创建了一个UserControl:
[Browsable(true)]
public string Text
{
get { return pnlLookupTable.GroupingText; }
set { pnlLookupTable.GroupingText = value; }
}
正如您可能已经猜到的那样,pnlLookupTable是一个Panel控件。我可以在“属性”窗口中更改Text属性的值,它会像标记一样反映在标记中。但是,页面内UserControl的设计视图不会显示Panel的更新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表单,并且我正在更改Text属性。我想在设计器中直观地看到Panel的GroupingText的更改。
答案 0 :(得分:6)
我必须回顾一下UserControlDesigner代码...
短篇小说:我认为这不可能。
这是长篇故事:
据我所知,位于ASCX文件中的用户控件永远不会在设计器中运行。也就是说,ASCX或ASCX.CS文件中的代码永远不会在Visual Studio中编译或运行。这是为了防止由于在CLR中无法卸载已加载的程序集而导致的内存泄漏。为了在用户控件中运行代码,Visual Studio必须将ASCX编译为DLL,然后加载它,然后运行代码。每次更改ASCX时,都必须再次执行此操作。每次执行此操作时,ASCX生成的额外加载的DLL将占用更多内存。
由于CLR中的这种限制,用户控件设计器实际上并不编译或运行ASCX文件。相反,它解析ASCX文件并在其中查找控件,而是加载这些控件。对于它在ASCX文件中找到的每个控件,它将创建关联的控件设计器并呈现该控件的设计时HTML。
有几种方法可以解决这个问题:
这两个解决方案应该起作用的原因是它们都涉及将代码编译成DLL。这个想法是DLL不会经常更改,因此Visual Studio加载DLL是安全的,而不必在每次DLL更改(以及泄漏内存)时重新加载它。
答案 1 :(得分:1)
我确信我已经找到了答案,然后把它全部写完了,但有些东西让我烦恼,所以我最后测试了几个小时。
事实证明(就像Eilon所说的那样),我认为你不能这样做。
ASCX控件完全忽略DesignerAttribute,因此您无法为它们指定自定义设计时渲染器。我认为“很好,我可以继承Panel控件并在其上指定一个新的设计器,它将从父控件中获取属性”。你猜怎么着?没有机会。如果您在设计器中访问Panel的父控件, 将不会强制转换为自定义用户控件类型 。我可以看到它是一个UserControl,除了我的TestUserControl之外它不可能是任何其他UserControl,但是如果我尝试强制转换它,设计器类会引发异常!
说实话,这让我心烦意乱。这基本上就是Eilon所说的 - 在设计模式下对Web用户控件有一个故意的限制。
虽然这对我来说是一个有趣的学习机会,但我很遗憾地报告说我不认为.ascx会削减它。我很确定即使将其编译为像Eilon建议的DLL也不会这样做。你可能不得不采用自定义控制路线。