Search code examples
c#asp.netbootstrap-4progress-barupdatepanel-progressbar

Bootstrap progress bar is not working in UpdatePanel - ASP.NET


I am trying to use the bootstrap progress bar in UpdatePanel (Ajaxtoolkit). I want to show the progress of the progress bar from a for loop. Following is the ASP.NET code

<div class="progress" style="width:80%;margin:auto;">
  <div id="divProgressBar" runat="server" class="progress-bar" role="progressbar" aria- 
  valuenow="0" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width: 0%;">
        0%
  </div>
</div>        

And following is the code for C#

intProgressBarCurrentPercentage += intProgressBarPercentageIncrement;

                divProgressBar.Style.Add("width", intProgressBarCurrentPercentage.ToString("F1") + "%");
                divProgressBar.Attributes.Add("aria-valuenow", intProgressBarCurrentPercentage.ToString("F1"));
                divProgressBar.InnerText = intProgressBarCurrentPercentage.ToString() + "%";                    

The problem is that the progress bar is not incrementing the progress when the new value is assigned to the progress bar.

I believe that this is because of the fact that the progress bar is in the UpdatePanel and I don't wish to move the progress bar outside the UpdatePanel.

I tried adding the progressbar in the trigger section of UpdatePanel but it isn't working.


Solution

  • This code works for me:

    Markup:

            <div class="progress" style="width: 30%; margin: auto;float:left">
                <div id="divProgressBar" runat="server" class="progress-bar" 
                    role="progressbar" >
                    <a href="../App_Data/">../App_Data/</a> aria-valuenow="0" 
                    aria-valuemin="0" 
                    aria-valuemax="100" 
                    style="min-width: 2em; width: 0%;">
                    0%
                </div>
            </div>  
    
            <br />
            <br />
            <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
            <br />
    
            <asp:Button ID="cmdIncrement" runat="server" Text="Increment"
                OnClick="cmdIncrement_Click"
                />
    

    Code behind:

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
                TextBox1.Text = "1";
            setbar(0);
        }
    
        protected void cmdIncrement_Click(object sender, EventArgs e)
        {
            const decimal MyMax = 10;
            int Count = Convert.ToInt32(TextBox1.Text);
            Count++;
            TextBox1.Text = Count.ToString();
            decimal MyPercent = Count / MyMax * 100;
            setbar(MyPercent);
        }
    
        void setbar(decimal MyPercent)
        {
            divProgressBar.Style.Add("width", MyPercent + "%");
            divProgressBar.Attributes.Add("aria-valuenow", MyPercent.ToString());
            divProgressBar.InnerText = MyPercent.ToString() + "%";
    
        }
    

    Result:

    enter image description here

    And the above ALSO works if I use a update panel.

    UpdatePanel (Ajaxtoolkit).

    NO!

    The Ajaxtoolkit is 100% separate and has nothing to do with the use of say update panels.

    The The AjaxToolKit is a library of controls like "accordion", "dialog", "ajaxfileupload" etc.

    However, use of update panels to adopt some ajax features in a web page is NOT related to the ajaxtoolkit, and you are free to use update panels without the ajaxtoolkit, and they are in fact not related to each other.

    I should also point out that the above sample posted code ALSO works if you place the above sample inside of a update panel.

    Edit: question author now wants a loop

    Remember, to do web development, you MUST grasp the concept of a page life cycle, or so called "round trip".

    Simple explanation:

    Changes made to the browser "DOM" by code behind are NEVER seen by the user DURING code running. A copy of the browser is up on the server, and as your code changes the browser (now up on the server), the end user just sees the browser wait/spinner. Only after all code runs and THEN the browser makes the trip back down to the client side does the user see the results.

    So, the page life cycle (a round trip) looks like this:

    You have this:

    enter image description here

    Note how your page class - code behind is NOT in memory on the server.

    YOU DO NOT have this:

    enter image description here

    And you do NOT even have this:

    enter image description here

    NOTE VERY careful here - the web page is ON CLIENT computer - it is NOT existing at all on the web server side.

    So, when you click on a button, or do a post-back, then you get the start of the round trip.

    This:

    enter image description here

    Our web page is sent up to the server. You now have this:

    enter image description here

    NOW a instance of the page class is created, and your code behind starts running.

    Your code behind can modify controls (even controls to be visible or not), but the page is NOT interacting with the user - ONLY code can MODIFY the web page (user does not see one change, or many changes).

    One change, or MANY changes to the web page can occur, but AS YOU update things like a text box etc., the user does NOT see these changes just yet. So, if you run a loop 1 to 10, and update a text box, the txt box WILL be updated 1 to 10. However, the end user sees nothing, since that web page (and code) is running up on the server.

    Changes to web page are occurring on the server - the client side browser does not have the web page any more!

    Once ALL of your code is done running, then and ONLY then does the page make the trip back to the client side browser.

    The server side class instance and code (and variables) are TOSSED OUT - DOES NOT exist! Your server side page class is disposed - removed from memory, and the web page code behind does NOT exist any more.

    So, page travels back to the client side, is re-displayed, JavaScript is loaded, and THEN JavaScript starts running. So even the client side page now 100% re-loads.

    enter image description here

    So, now armed with the above knowledge of a post back and round type (the page life cycle)?

    OK, this means that to display changes to the web page, the page MUST do a round trip. And if you using a update-panel, then that update panel MUST make a round trip!

    The other approach for such a loop? You use client side JavaScript code.

    However, let's take our above existing example, and when we click start, let's loop 1 to 10, but REMEMBER, we need round trips to display the browser updates!

    So, since we need round trips, then most easy is to drop in a timer control onto the page. (this means we don't have to learn and write some JavaScript code).

    So, let's also use a update panel. (Remember, a update panel STILL has the above full page life cycle - even page load will fire and run EVERY time - even with a update panel).

    So, now we have this markup:

            <asp:ScriptManager ID="ScriptManager1" runat="server">
            </asp:ScriptManager>
    
            <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                <ContentTemplate>
    
                    <div class="progress" style="width: 30%; margin: auto; float: left">
                        <div id="divProgressBar" runat="server" class="progress-bar"
                            role="progressbar">
                            <a href="../App_Data/">../App_Data/</a> aria-valuenow="0" 
                    aria-valuemin="0" 
                    aria-valuemax="100" 
                    style="min-width: 2em; width: 0%;">
                    0%
                        </div>
                    </div>
    
                    <asp:Timer ID="Timer1" runat="server" 
                        Enabled="False" Interval="1000" OnTick="Timer1_Tick">
                    </asp:Timer>
                    <br />
                    <br />
                    <asp:Button ID="cmdStart" runat="server" Text="Start"
                        CssClass="btn"
                        OnClick="cmdStart_Click"
                        />
                    <asp:HiddenField ID="HMyCount" runat="server" />
    
    
                </ContentTemplate>
            </asp:UpdatePanel>
    

    And this code:

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
                setbar(0);
        }
    
        protected void cmdStart_Click(object sender, EventArgs e)
        {
            HMyCount.Value = "0";
            Timer1.Enabled = true;
        }
    
        protected void Timer1_Tick(object sender, EventArgs e)
        {
            const decimal MyMax = 10;
            int Counter = Convert.ToInt32(HMyCount.Value);
            Counter++;
            HMyCount.Value = Counter.ToString();
    
            if (Counter > 10)
            {
                Timer1.Enabled = false; // stop our timer
                return;
            }
            decimal MyPercent = Counter / MyMax * 100;
            setbar(MyPercent);
    
        }
        void setbar(decimal MyPercent)
        {
            divProgressBar.Style.Add("width", MyPercent + "%");
            divProgressBar.Attributes.Add("aria-valuenow", MyPercent.ToString());
            divProgressBar.InnerText = MyPercent.ToString() + "%";
    
        }
    

    And now the result is this:

    enter image description here

    I should post a working JavaScript example, since again, we could run this code 100% client side, and that would mean no post-backs, and no round trips are required.