Как обновить интерфейс UserControl во время разработки на основе значения свойства? - PullRequest
5 голосов
/ 14 января 2010

Я создал UserControl со следующим открытым свойством:

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

pnlLookupTable - это, как вы уже догадались, элемент управления Panel. Я могу изменить значение свойства Text в окне Properties, и оно будет отражено в разметке, как и должно быть. Однако в конструктивном представлении UserControl внутри страницы не отображается обновленный GroupingText для Panel. Как я могу это сделать?

EDIT

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

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>

Я изменил некоторые идентификаторы и другие тривиальные вещи для защиты собственной природы кода.

Я также должен повторить, что я смотрю на веб-форму в режиме разработки, в которой добавлен мой элемент управления, и я изменяю свойство Text. Я хочу увидеть изменение GroupingText панели визуально в конструкторе.

Ответы [ 2 ]

6 голосов
/ 17 января 2010

Мне нужно немного вспомнить код UserControlDesigner ...

Короткая история: я не думаю, что это возможно.

А вот и длинная история:

Насколько я помню, пользовательские элементы управления, расположенные в файлах ASCX, никогда не запускаются в конструкторе. То есть код внутри файла ASCX или ASCX.CS никогда не компилируется и не запускается в Visual Studio. Это необходимо для предотвращения утечек памяти, вызванных тем, что в CLR вы не можете выгружать загруженные вами сборки. Для запуска кода в вашем пользовательском элементе управления Visual Studio должна скомпилировать ASCX в DLL, затем загрузить его и запустить код. Каждый раз, когда вы вносите изменения в ASCX, ему придется выполнять эту операцию снова. Каждый раз, когда происходит эта операция, дополнительно загружаемая DLL, сгенерированная из вашего ASCX, будет использовать больше памяти.

Из-за этого ограничения в CLR конструктор пользовательских элементов управления фактически не компилирует и не запускает файл ASCX. Вместо этого он анализирует файл ASCX и ищет в нем элементы управления, а вместо этого загружает эти элементы управления. Для каждого элемента управления, найденного в файле ASCX, он создаст соответствующий конструктор элемента управления и отобразит HTML времени разработки этого элемента управления.

Есть несколько способов обойти это:

  1. Вместо использования пользовательского элемента управления ASCX вы можете написать обычный пользовательский элемент управления, производный от Control, а код записывается в файл CS или VB.
  2. Скомпилируйте ASCX в DLL. Дэвид Эббо написал в блоге о том, как это сделать.

Причина, по которой эти два решения должны работать, заключается в том, что оба они включают в себя компиляцию кода в DLL. Идея состоит в том, что DLL не меняется очень часто, поэтому для Visual Studio безопасно загружать DLL без риска ее перезагрузки при каждом изменении DLL (и утечке памяти).

1 голос
/ 17 января 2010

Я подумал наверняка, что у меня есть ответ на этот вопрос, и написал все это, но что-то беспокоило меня в этом, так что я закончил тестировать это в течение нескольких часов.

Оказывается, (как сказал Эйлон), я не думаю, что вы можете сделать это.

Элементы управления ASCX полностью игнорируют DesignerAttribute , поэтому вы не можете указать для них настраиваемое средство визуализации времени разработки. Я подумал: «Хорошо, я могу создать подкласс для элемента управления Panel и указать новый конструктор, который будет получать свойства из родительского элемента управления». Угадай, что? Без шансов. При доступе к родительскому элементу управления Panel в конструкторе он не будет приведен к пользовательскому типу пользовательского элемента управления . Я вижу, что это UserControl, и это не может быть любой другой UserControl, кроме моего TestUserControl, но класс конструктора выдает исключение, если я пытаюсь привести его!

Это поражает, если честно. По сути, это именно то, о чем говорит Эйлон, - существует преднамеренное ограничение веб-управления пользователями в режиме разработки.

Вот расплывчатое сообщение от Стивена Ченга, в котором говорится, что поддержка времени разработки не нужна для пользовательских веб-контролей.

Хотя это была забавная возможность для меня, извините, что сообщаю, что я не думаю, что .ascx его урежет. Я почти уверен, что даже компиляция в DLL, как предположил Эйлон, этого не сделает. Вам, вероятно, придется пройти маршрут пользовательского управления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...