вторник, 9 марта 2010 г.

Пишем CMS. Шаг № 4. Показываем пользователю результат действия

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

Итак, как же сказать пользователю "Все в порядке!"? Первое, что приходит в голову - разместить на странице Label, в методе обработке результата менять цвет и текст в зависимости от результата. Что мне не нравится в этом подходе? Ну допустим мы определяем внешний вид стилями, которые храним в файле CSS, одном на весь сайт. А что, если мы захотим рядом с текстом добавлять картинку или еще как-то украсить его? Будет весьма затруднительно поменять Label на Div на всех страницах, где мы используем сообщения. Поэтому мы так делать не будем. А мы поэтому создадим простой пользовательский контрол. Делается это очень просто:

1. Добавляем новый item в наш проект (предлагаю сначала создать папку Controls и хранить все контролы там), выбираем тип Web User Control.

2. Открываем файл ascx и добавляем такую панель:

  <asp:Panel ID="panelInfo" runat="server" Visible="true">
    <asp:Label ID="labInfo" runat="server" Text="" CssClass="LabelInfo"></asp:Label> <p></p> 
    <asp:HyperLink ID="linkInfo" runat="server">
      <asp:Label ID="labLink" runat="server" Text=""></asp:Label>
    </asp:HyperLink>
  </asp:Panel>


* This source code was highlighted with Source Code Highlighter.



Мы видим, что внутри панели размещается одна метка (текст сообщения), а также ссылка, внутри которой размещается еще одна метка. Это будет та ссылка, по которой мы предложим перейти пользователю, и по которой он обязательно перейдет, если его браузер не поддерживает автоматическое перенаправление.

Теперь заглянем в код. У меня это выглядит так:

public void Activate(bool? IsResultOK, string Message, string LinkLabelCode, string Link)
    {
      this.Visible = true;
      if (IsResultOK == null)
      {
        panelInfo.CssClass = "PanelInfoFYI";
      }
      if (IsResultOK.Value)
      {
        panelInfo.CssClass = "PanelInfoOK";
      }
      else if (!IsResultOK.Value)
      {
        panelInfo.CssClass = "PanelInfoFail";
      }
      if (Message != string.Empty)
        labInfo.Text = Message;
      if (LinkLabelCode != string.Empty && Link != string.Empty)
      {
        linkInfo.Visible = true;
        string linkText = LinkLabelCode;
        linkInfo.Text = linkText;
        labLink.Text = linkText;
        linkInfo.NavigateUrl = Link;
      }
      else
        linkInfo.Visible = false;
    }


* This source code was highlighted with Source Code Highlighter.



Первый параметр говорит о том, каков результат - если все плохо (false), то подключаем стиль ошибки, если хорошо (true) - положительный результат. Иногда требуется просто проинформировать пользователя, в этом случае передадим null и отобразим сообщение голубеньким.

Теперь посмотрим, как происходит вызов этого метода. После того, как мы положили на форму наш контрол (не забываем о регистрации - <%@ Register src="../Controls/InfoPanel.ascx" tagname="InfoPanel" tagprefix="controls" %> ), мы можем обращаться к нему напрямую:


if (result)
panelInfo.Activate(true, Messages.LanguageSaveOK, Messages.LabelLinkToLanguages, Pages.Languages);


Вот тут немного интереснее. Что это за Messages и Pages? Это имена ресурсных файлов (вернее, классов, которые сгенерировались как только мы добавили файл ресурса). Зачем, спрашивается? Нам нужно, чтобы ссылка отображала текст. Мы, конечно, можем просто захардкодить этот текст, но, во-первых, мы с самого начала договорились, что будем писать красивый код, а во-вторых, и это, конечно, главное, подобный подход может привести к очень большому геморрою в будущем. Представим себе, что мы таким образом захардкодили сообщений эдак... двести по всему проекту... а потом пришла директива сверху: все сообщения начинать со слов "Дорогой пользователь!" И вот мы ползаем по сайту, и, чертыхаясь, исправляем все двести сообщений...

В-общем, наши сообщения мы будем хранить в ресурсных файлах. Если что, его даже без проблем можно будет перевести на другие языки. Но сейчас для наших целей нам нужно два обычных ресурсных файла. Один - для сообщений, второй - для адресов страниц. Второй, возможно, нам в будущем не понадобится (пока не могу точно сказать), но пока что он избавляет от необходимости хардкодить ссылки, по которым надо переходить.

Можно, конечно, хранить сообщения в отдельном классе, но по-моему, в ресурсах хранить удобнее. Теперь мы с легкостью можем ссылаться на любые переменные, добавленные в текстовый ресурс, кроме того, студия позволяет сортировать переменные по именам и значениям, что, согласитесь, очень удобно. Значения, которые мы забиваем в табличке ресурсов, можно посмотреть в файле <НазваниеРесурса>.designer.cs

В следующем шаге мы перенаправим пользователя на указанную страницу.

Комментариев нет: