none
ASPX AJAX Update UpdatePanel на внешнее событие

    Вопрос

  • Добрый день!

    Пишу чат для процесса согласования договоров. Чат находится среди прочих Контролов на WebPart. WebPart появляется при редактировании Задачи на согласование договора и заполняется всем необходимым для принятия решения, в том чиcле есть чат. Сам Чат, состоит из Текст бокса вывода всех постов (здесь же UpdatePanel2 ), Текст бокса для ввода очередного поста (здесь же UpdatePanel1) и кнопки Отправить очередной пост. Оба Текста завернуты в UpdatePanel.

    При отправки очередного поста обновляется UpdatePanel1 и UpdatePanel2 - Здесь всё ОК.

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

    Начал решать этот вопрос так:

    1. Создал событие, которое возникает когда в списке, содержащем чат что то меняется.

    2. В событии сравниваю ID моего элемента на экране и элемента который создал событие изменения в списке, и если ID совпадают, то ставлю статик переменную NeedRefrash в True.

    3. А вот дальше у меня затык... Думал по таймеру проверять переменную NeedRefrash и делать Updatepanel2.Update(), но не тут то было. Таймер, если его не прописывать в Тригерах UpdatePanel начинает вызывать Page_Load. Если прописываешь, то он просто обновляет панель раз например в 5 секунд без всякого внешнего события. Конечно, можно было бы сделать обновление просто по таймеру, но это не удобно, когда начинаешь просматривать кто что написал и после Update() Текст позиционируется с начала. Другими способами пробовал - не всегда Контролы доступны и.т.д.

    Кто то решал похожую задачу? С какой стороны подходить?

           <td colspan="2" "><strong>Чат:</strong></td>
        </tr>
        <tr>
            <td colspan="2" class="auto-style11" >
                <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                    <ContentTemplate>
                        <asp:TextBox ID="TextBox1" runat="server" Height="100%" Width="100%" TextMode="MultiLine" ReadOnly="True" Rows="6" ></asp:TextBox>
                    </ContentTemplate>
                    
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="ChatSend" />
                    </Triggers>
                    
                </asp:UpdatePanel>
            </td>
        </tr>
        <tr>
            <td Width="85%" aria-multiline="False">
                <asp:UpdatePanel ID="UpdatePanel2" runat="server">
                    <ContentTemplate>
                <asp:TextBox ID="TextBox2" runat="server" Width="100%" Height="100%"></asp:TextBox>
                        </ContentTemplate>
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="ChatSend" />
                        <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick"/>
                    </Triggers>
                </asp:UpdatePanel>
            </td>
            <td Width="15%" >
                <asp:Button ID="ChatSend" runat="server" Text="Отправить" Height="100%" Width="100%" OnClick="ChatSend_Click" UseSubmitBehavior="False" />
            </td>
        </tr>
    
    </table>
    
    <asp:Timer ID="Timer1" runat="server" OnTick="Timer1_Tick" Interval="5000">
    </asp:Timer>




    • Изменено agemlex77 17 июля 2017 г. 5:48 уточнение
    17 июля 2017 г. 5:46

Ответы

  • Вам обязательно делать все именно на этой технологии 10 летней давности?

    Если нет то на сервере делается REST API который ждет произвольных обновлений в течении какого то времени (минуты например) и возвращает информацию о том есть обновления или нет.

    Клиент вызывает данный API и по возврату либо производит обновление чего надо, либо делает еще один вызов.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа agemlex77 19 июля 2017 г. 3:17
    18 июля 2017 г. 5:45

Все ответы

  • Тут мой коллега, высказал безумную идею: А что если пробежаться по всем сессиям и обновить панели у всех, кто в твоём же чате?

    Так вот вопрос, есть ли возможность получить доступ к UpdatePanel другого пользователя? Там какая ни будь коллекция контекстов пользователей или ещё чего ни будь...

    18 июля 2017 г. 2:23
  • ОК, может стоит пойти с другой стороны. Действительно сделать обновление по таймеру, но при этом найти способ сохранить Скроллинг в TextBox в том же положении, что и до PostBack (Обновления). Нашел несколько подобных вещей, ставил в Page_Load Page.MaintainScrollPositionOnPostBack = true; , но при обновлении скрол слетает на начало.

    https://jerryyasir.wordpress.com/2008/03/17/maintaining-page-scroll-position/ 

    Идеи?

    18 июля 2017 г. 5:00
  • Вам обязательно делать все именно на этой технологии 10 летней давности?

    Если нет то на сервере делается REST API который ждет произвольных обновлений в течении какого то времени (минуты например) и возвращает информацию о том есть обновления или нет.

    Клиент вызывает данный API и по возврату либо производит обновление чего надо, либо делает еще один вызов.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа agemlex77 19 июля 2017 г. 3:17
    18 июля 2017 г. 5:45
  • Нет не обязательно использовать старые технологии. Важно решить задачу. 

    У меня проблема сейчас только с перерисовкой. Нужно сделать так, чтобы, если человек просматривал чат находящийся в TextBox1, то обновление (перерисовка), какой бы технологией это не было сделано, не сдвигала скролинг на начало TextBox, и не мешала смотреть посты.

    Я полез в javascript и пока не могу получить объект textbox. При записи в координат скролинга vs кричит, что он объект null.

    var objDiv = document.getElementById("TextBox1");
           objDiv.scrollLeft=50;
           objDiv.scrollTop=50;

    18 июля 2017 г. 6:03
  • Ну так наверное и не должно быть никакого текстбокса. А должны быть объекты с сообщениями в контейнере со скролингом, видимо с поддержкой модели для каждого сообщения объектом javascript. По мере прихода новых сообщений они просто добавляются в контейнер с конца.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    18 июля 2017 г. 6:50
  • Сейчас я использую asp:TextBox многострочный для отображения постов. Что я должен использовать для отображения постов? Контейнер? Что за контейнер? 

    Дело в том, что вы очень пространно пишите для того, чтобы я понял всю глубину предложенного вами способа. Можно немного конкретнее.

    Ок, допустим я написал REST API. Что дальше?

    Вот у меня есть WebPart (или нужно не WebPart использовать). Теперь мне нужно, чтобы раз в какое то время (это как сделать по таймеру, который у меня уже есть?) приложение делало запрос через REST API? 

    У меня сейчас добавляются сообщения в List и я с помощью Query вытаскиваю сообщения в обратном порядки и отображаю в TextBox1.

    Я честно говоря не понимаю, какую проблему решит использование REST API?

    Данные сами будут обновляться в элементах без всяких обработок или что? Те статьи которые я читал говорили только о том, что можно получать данные, а какие ещё есть преимущества?

    В общем прошу конкретики или ссылки с конкретикой.


    • Изменено agemlex77 18 июля 2017 г. 7:25 correction
    18 июля 2017 г. 7:21
  • Используя  REST API вы получаете следующее.

    Клиент делает запрос веб службе: есть новое? служба ему ответ:  да  на возьми это все и получи. На клиенте ты получаешь JSON объект например, и с помощью JS берешь что нужно и вставляешь куда нужно(в данном случае в конец чата). Запрос к серверу приложения при этом вообще не происходит, только первый раз при загрузке страницы.  Как то так. Вообще вариантов множество как это реализовать. 

    18 июля 2017 г. 8:07
  • Ок, спасибо всем за ответы. Теперь нужно осмыслить.

    Пока я до конца не понимаю в чём собственно польза и вот почему: В процессе обсуждения я уже написал обработчик (EventReceiver), который даёт мне возможность понять есть новые данные или нет. Я и так уже делаю запрос и получаю ответ, что есть что то новое при помощи Query. Что я получу при работе с Rest API? Возможность работы из javascript? Она вроде и так у меня есть. Использование более новой технологии. Ну хорошо, согласен, я переделаю всё под Rest API. Но проблема то останется. Или нет?

    У меня осталась только одна проблема. Как мне обновить данные (я уже знаю, что они обновились. Могу их читать), чтобы у меня не уходил с установленного места скроллинг элемента в котором у меня весь чат?

    Если я javasript-ом запишу в поле данные, где весь чат, новый или добавлю в конец текст, то у меня на экране это обновится сразу? Скроллинг не съедит?

    18 июля 2017 г. 8:25
  • Не обновляйте полностью чат, добавьте с помощью JS новый элемент(ы) в конец списка.

    18 июля 2017 г. 9:46
  • Дело в том, что у меня наоборот - новые посты добавляются в начало списка, но это ладно.

    Получилось у меня запоминать скроллинг. Теперь у меня при обновлении экран никуда не дёргается и раз в 10 секунд проверяет новые сообщения. Но при обновлении становятся на секунду неактивными иконки меню и в общем то обновление видно. Теперь я полностью осознал, о чём мне говорили Гуру в постах выше. Нужно все операции обновления производить из javascript тогда вообще не будет видно обновления, а посты будут появляться сами собой. Даже не важно в конец или начало я добавляю текст. Именно для этого, чтобы я мог получать данные в javascript мне нужно REST API, которое может быть вызвано хоть откуда.

    Ещё раз спасибо за ответы!

    Выкладываю пример кода с запоминанием скроллинга может пригодится кому:

        <tr>
            <td> 
                <asp:TextBox ID="X1" runat="server" value="0">
    </asp:TextBox><br /> // Можно переделать на HiddenField
                <asp:TextBox ID="Y1" runat="server" value="0"></asp:TextBox>
            </td>
            <td><asp:Button ID="Refresh" runat="server" Text="Обновить" Height="100%" Width="100%" OnClick="Refresh_Click" UseSubmitBehavior="False" ValidateRequestMode="Disabled" CausesValidation="False" EnableTheming="False" EnableViewState="False" ViewStateMode="Disabled" AccessKey="O" /></td>
        </tr>
    
    </table>
    <script language="javascript">
    
    <!--
        function sstchur_SmartScroller_GetCoords() {
            document.getElementById("<%= X1.ClientID %>").value = document.getElementById("<%= TextBox1.ClientID %>").scrollLeft;
            document.getElementById("<%= Y1.ClientID %>").value = document.getElementById("<%= TextBox1.ClientID %>").scrollTop;
        }
       
        function sstchur_SmartScroller_Scroll() {
            document.getElementById("<%= TextBox1.ClientID %>").scrollLeft = document.getElementById("<%= X1.ClientID %>").value;
            document.getElementById("<%= TextBox1.ClientID %>").scrollTop = document.getElementById("<%= Y1.ClientID %>").value;
        }
       
        window.onload = sstchur_SmartScroller_Scroll;
    
       document.getElementById("<%= TextBox1.ClientID %>").onscroll = sstchur_SmartScroller_GetCoords;
    // -->
    </script>




    • Помечено в качестве ответа agemlex77 18 июля 2017 г. 11:42
    • Снята пометка об ответе agemlex77 19 июля 2017 г. 3:10
    • Изменено agemlex77 19 июля 2017 г. 3:18 Осознал
    18 июля 2017 г. 11:42