Конференция ".Net" » Нотификация изменений свойств WebControl-а [C#]
 
  • kaif © (05.11.07 17:06) [0]
    Пытаюсь в ASP.NET добиться того, что в Delphi делается весьма просто. Но пока результата нет.

    Предыстория.
    Я создал некий TabSource: Control, в данном случае это компонент, содержащий свойства PageCount и PageIndex. Идея в том, что он будет хранить "текущую страницу" результатов поиска в базе данных. Сам поиск будет использовать SQL-конструкции типа

    SELECT FIRST 20 SKIP 3 <поля> FROM <и так далее...>, то есть меня как бы не совсем устраивает то, как это организовано в стандартном GridView и я хочу написать свою поддержку страниц, которая бы не мучила сервер большими выборками.

    Далее я создал некий TabControl: WebControl, который умеет отображать страницы в цикле 0 ... PageCount - 1 и через механизм обратного вызова скрипта __doPostBack() перепосылать Web-форму на сервер. Этот компонент имеет свойство TabSource, к которому в инспекторе объектов можно назначить тот первый компонент, который я описал выше. Почему я сделал два компонента? Потому что я хочу иметь возможность поставить "отображатель страницы" в нескольких местах формы, скажем над сеткой и под ней, но привязать оба таких серверных компонента к общему источнику, содержащему PageCount.

    Компоненты у меня работают. После изменения PageCount в инспекторе объектов у первого компонента TabSource1, если изменить значение свойства TabSource у второго компонента TabControl1 с (none) на TabSource1 тот пересвечивается даже в дизайнере и отображает нужное число страниц в виде цифр. Однако автоматически изменение совйства PageCount у первого компонента, естественно не приводит к пересветке второго компонента. Хочется сделать так чтобы это происходило.

    По опыту Delphi я знаю, что нужна какая-то нотификация "компонентов, ссылающихся на данный" и помню, что в Delphi это было сделано как-то весьма элегантно, во всяком случае проблем с написанием компонентов, которые можно было друг к другу подключать, удалать и изменять их свойства в режиме дизайна, я не испытывал.

    Пытаясь реализовать что-то подобное в ASP.NET, нашел довольно грубый механизм, точнее его одну только часть - интерфейс
    INotifyPropertyChanged

    .
    Этот интерфейс позволяет сгенерировать при изменении значения свойства некое "стандартное" событие PropertyChanged и передать в него в виде аргумента строковое представление имени свойства или что-то более хитрое, но в любом случае это должна быть строка.

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

    Идеально было бы, конечно, если бы он сам как-то догадался, видя, что имеет свойство типа класса, реализующего интерфейс INotifyPropertyChanged. Но он сам не догадывается. А как заставить его "догадываться", я никак не могу сообразить. Как "на зависимой стороне" организовать реагирование на изменение значения свойства?

    Во всех примерах, какие я нахожу на google или MSDN, описывается связывание (binding) со списками, но мне не нужен пока никакой список. Мне нужно банально заставить пересветиться контролу, который имеет свойством иной контрол, если тот контрол изменил значение некоторого существенного для этого контрола свойства.

    Кто знает самое простое решение этой проблемы?

    интерфейс INotifyPropertyChanged реализован.

    public class TabSource: System.Web.UI.Control, INotifyPropertyChanged
     {
       public event PropertyChangedEventHandler PropertyChanged;

       private void NotifyPropertyChanged(String info)
       {
         if(PropertyChanged != null)
         {
           PropertyChanged(this, new PropertyChangedEventArgs(info));
         }

       }

       private int pageCount;
       
       [Category("Data")]
       [DefaultValue("10")]
       public int PageCount
       {
         get { return this.pageCount; }

         set
         {
           if(value != this.pageCount)
           {
             this.pageCount = value;
             NotifyPropertyChanged("PageCount");
           }

         }
       }
    ...



    А что нужно сделать в классе TabControl, чтобы он это событие "поймал" ?

    public class TabControl: System.Web.UI.WebControls.WebControl, IPostBackEventHandler
     {
       private TabSource tabSource = null;

       public TabSource TabSource
       { get { return tabSource; }
    set
      { tabSource = value; } }
    ....



    Может быть достаточно добавить некий интерфейс и реализовать один его метод и все бы у меня заработало?
    Прошу помочь тех, кто знает.
  • b z (05.11.07 18:46) [1]
    посмотрите как реализован к примеру GridView, думаю вам надо что-то подобное делать
    ... под вебом, как правило, такие вещи делают через ViewState
  • kaif © (06.11.07 17:07) [2]
    А что, я могу посмотреть где-то исходный код GridView? Я об этом ничего не знал. В Delphi очень удобно то, что исходный код почти всей VCL выложен открыто. В MVS когда я нажимаю F12 я попадаю на описание методов класса. Реализация от меня скрыта. Может быть есть какая-то еще кнопка, чтобы увидеть реализацию?
  • b z (06.11.07 17:20) [3]
  • kaif © (06.11.07 17:37) [4]
    2 b z   (06.11.07 17:20) [3]
    Спасибо! Очень интересно... Уже скачал.
    Обязательно поставлю и посмотрю.
  • Игорь Шевченко © (07.11.07 13:09) [5]
    Насколько я помню, Дино Эспозито в своем двухтомнике "Программирования для ASP.Net" весьма подробно описывает аспекты создания WEB-контролов и их потрохов.

    Рекомендую.
  • DiamondShark © (07.11.07 16:20) [6]

    > А как заставить его "догадываться", я никак не могу сообразить

    Заставить элкментарно: в нужном месте запросить интерфейс.
    Подходящим местом будет, скажем, сетер свойства TabControl.TabSource:

    class TabControl
    {
    ...
    TabSource TabSource
    {
    ...
    set
    {
    ...
    if (value is INotifyPropertyChanged)
    {
    // Ура! догадались! тут можно подписываться на события
    }

    }

    }
    ...
    }
  • kaif © (07.11.07 18:48) [7]
    2 DiamondShark ©   (07.11.07 16:20) [6]

    Спасибо. Твою идею я уловил. Попробовал добавить в мой "зависимый" класс метод с сигнатурой, как у делегата PropertyChangedEventHandler. И приплюсовал этот метод к событию PropertyChanged интерфейса. Однако что делать внутри этого метода, я не заю. Это WebControl и как он пересвечивается в дизайнере, мне пока невдомек. Метода Refresh у него нет.

    public TabSource TabSource
       {
         get { return _tabSource; }

         set
         {
           _tabSource = value;
           if(value is INotifyPropertyChanged) {
             value.PropertyChanged += TabSourcePropertyChanged;
           }

         }
       }
       public void TabSourcePropertyChanged(object sender, PropertyChangedEventArgs e){
         //не ясно, что здесь писать. Метода Refresh у компонента нет.
       }



    Кстати, еще до того, как я начал это проделывать, я обнаружил неприятную вещь. Если назначить свойству TabSource компонент TabSource1, то все вроде работает, дизайнер сразу отображает нужое число цифр. Однако если переключиться из режима визуального дизайна в режим просмотра текса формы и обратно, дизайнер тут же теряет понимание этой ссылки и вместо моего контрола TabControl выводит компонент с текстом ошибки, смысл которой состоит в том, что тот не может создать объект TabSource1 (тот, на который ссылается свойство) по его имени. Хотя этот объект на форме имеется и в дизайнере великолепно отображается.

    офф-топ: вчера сломал кисть руки, пишу левой рукой - извините, если допускаю ошибки.
  • kaif © (07.11.07 19:05) [8]
    2 Игорь Шевченко ©   (07.11.07 13:09) [5]
    Спасибо, Игорь.
    Благодаря твоему посту, почитав аннотации, я все же не поскупился и заказал на Озоне две книги Дино Эспозито: базовый курс и углубленное изучение ASP.NET 2.0. Надеюсь он мне поможет во всем досконально разобраться. А то первоначально я купил Байдачного, Маленко ASP.NET 2.0 - мне показалось, что хорошо написано и я отступил от своего правила не покупать наших авторов ни при каких условиях. Книга оказалась неплохой, но с пробелами. В частности очень нечетко описано все, что касается делегатов и событий. И много путаницы в тексте - иногда понимаеншь, что понимать следует прямо наоборот тому, что написано... Хотя в целом эта книга позволила мне хоть как-то начать и даже умудриться написать и зарегистрировать свои собственные классы  провайдеров аутентификации и авторизации под Интербейс, что меня очень вдохновило.

    Может быть мне имеет смысл подписаться на журнал RSDN? Я заметил, там много полезной информации бывет.
  • Игорь Шевченко © (08.11.07 11:06) [9]
    kaif ©   (07.11.07 19:05) [8]


    > Может быть мне имеет смысл подписаться на журнал RSDN? Я
    > заметил, там много полезной информации бывет


    Да, конечно. Смысл имеет, тем более, что это последний из оставшихся в живых журналов для программистов. Собственно, у меня подборка этих журналов с момента основания до 2006 года включительно, ни в коей мере не считаю макулатурой.
    Кстати, имеет смысл подписаться также на MSDN Magazine RE - там тоже много полезного, а главное - перечень авторов, на который можно ориентироваться при выборе книг :)

    А что касается книжек, то я и зарубежных-то не очень покупаю, прежде чем не узнаю, что автор мне известен по предыдущим публикациям.
  • kaif © (13.11.07 12:21) [10]
    Все! Держу в руках "Базовый курс" и "Углубленный курс" ASP.NET 2.0 Дино Эспозито. Потрясающая литература.
    Спасибо, Игорь!
    Я - твой должник.
    Разница между этими книгами и тем, чем я пока пользовался, напоминает разницу между лекарством и биодобавкой.
    :)
  • Игорь Шевченко © (13.11.07 15:52) [11]
    kaif ©   (13.11.07 12:21) [10]

    Мне повезло больше - я кроме Эспозито ничего по этой теме не читал :) Кроме его и Рихтера статей в MSDN Magazine RE.
 
Конференция ".Net" » Нотификация изменений свойств WebControl-а [C#]
Есть новые Нет новых   [118230   +17][b:0][p:0.002]