【问题标题】:How to update design-time UserControl interface based on property value?如何根据属性值更新设计时 UserControl 界面?
【发布时间】:2010-01-14 05:01:54
【问题描述】:

我创建了一个具有以下公共属性的 UserControl:

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

pnlLookupTable 正如您可能已经猜到的那样,是一个面板控件。我可以在“属性”窗口中更改 Text 属性的值,它会像应有的那样反映在标记中。但是,页面内 UserControl 的设计视图不会显示更新后的 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 的变化。

【问题讨论】:

  • 您是如何实现用户控制的?作为一个包含代码的 ASCX 文件?或者您是否编写了一个派生自 UserControl 的自定义类?请从您的场景中显示更多代码,因为这会影响答案。
  • Eilon,我更新了我的帖子。没有太多可看的了。 :)
  • 快速跟进:我认为是时候接受这件事无法完成并继续前进了。由于这实际上只是为了方便,因此不需要创建自定义控件或编译 .ascx,尽管这些都是很好的建议。感谢大家的贡献。我确实学到了一些东西。

标签: asp.net visual-studio-2008 user-controls webforms designer


【解决方案1】:

我不得不回想一下 UserControlDesigner 代码...

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

长篇大论:

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

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

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

  1. 您可以编写一个从 Control 派生的常规自定义控件,而不是使用 ASCX 用户控件,并将代码编写在 CS 或 VB 文件中。
  2. 将 ASCX 编译成 DLL。 David Ebbo 写了一封 blog post 来说明如何做到这一点。

这两个解决方案应该起作用的原因是它们都涉及将代码编译到 DLL 中。这个想法是 DLL 不会经常更改,因此 Visual Studio 加载 DLL 是安全的,而不必在每次 DLL 更改(和泄漏内存)时重新加载它的风险。

【讨论】:

  • 感谢 Eilon 提供的信息。我想知道该博客文章中的解决方案是否适用于 VS 2008,或者是否有任何变化。无论如何,它给了我一个很好的起点,让我做更多的研究。
  • 这种行为在 VS2005、VS2008 和 VS2010 中是相同的。我不知道有任何改变这种行为的计划。
  • 我刚刚读到为什么不能卸载程序集,这很有趣。这现在更有意义了。
【解决方案2】:

我以为我肯定有这个答案,并把它全部写出来,但有些东西困扰着我,所以我最终测试了几个小时。

事实证明(就像 Eilon 所说的那样),我认为您无法做到这一点。

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

说实话,这让我大吃一惊。这基本上正是 Eilon 所说的——在设计模式下对 web 用户控件有一个有意的限制。

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

虽然这对我来说是一个有趣的学习机会,但我很遗憾地报告说,我认为 .ascx 不会削减它。我很确定即使将它编译成像 Eilon 建议的 DLL 也不会这样做。您可能必须走自定义控制路线。

【讨论】:

  • 感谢您的努力,womp。这也将帮助我更深入地挖掘。我承认这可能是不可能的,但我和你一样很好奇,想知道为什么。
猜你喜欢
  • 1970-01-01
  • 2013-08-12
  • 2011-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多