[CLOSED] Setting ListView.SelectedIndex on server side fails

  1. #1

    [CLOSED] Setting ListView.SelectedIndex on server side fails

    Consider following example page which initializes SelectedIndex of a ListView:
    <%@ Page language="C#" autoeventwireup="true" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Test Page</title>
    </head>
    <body>
        <form runat="server" id="wForm">
            <asp:ScriptManager runat="server" id="wScriptManager" />
            <ext:ResourceManager runat="server" id="wResourceManager" sourceformatting="true" scriptmode="Debug" />
            <div runat="server" id="wRoot">
                <ext:Window runat="server" id="wDialog" width="150" height="400" layout="Fit">
                    <Items>
                        <ext:Panel runat="server" layout="Fit">
                            <Items>
                                <ext:ListView runat="server" hideheaders="true" singleselect="true" selectedindex="0">
                                    <Store>
                                        <ext:Store runat="server" id="wStore">
                                            <Reader>
                                                <ext:ArrayReader>
                                                    <Fields>
                                                        <ext:RecordField name="Name" type="String" />
                                                    </Fields>
                                                </ext:ArrayReader>
                                            </Reader>
                                        </ext:Store>
                                    </Store>
                                    <Columns>
                                        <ext:ListViewColumn dataindex="Name" />
                                    </Columns>
                                    <Listeners>
                                        <SelectionChange fn="function(){if(this.getSelectionCount()!=1){debugger;}}" />
                                    </Listeners>
                                </ext:ListView>
                            </Items>
                        </ext:Panel>
                    </Items>
                </ext:Window>
            </div>
        </form>
    </body>
    </html>
    <script runat="server" visible="false">
        protected void Page_Load()
        {
            wStore.DataSource = new object[] { new object[] { "A" }, new object[] { "B" }, new object[] { "C" } };
            wStore.DataBind();
        }
    </script>
    This randomly fails to initialize SelectedIndex, causing the list view selection to start empty. For debugging I added a listener to SelectionChange and it will trigger in the failure case. (Note that it depends a lot on timing so it may or may not reproduce reliably for you, but see below for my analysis of the problem.)

    The root of the call chain is Ext.ux.data.PagingStore.execute which contains following code fragment:
    if (action === "read" && this.isPaging(params)) {
        (function () {
            ...
            this.fireEvent("datachanged", this);
            ...
        }).defer(1, this);
    From there the call chain is
    - Ext.DataView.onDataChanged
    - Ext.DataView.refresh
    - Ext.DataView.clearSelections

    Which then leaves the selection empty if it runs after the selection has been initialized.


    So the root cause seems to be some indeterminisim when the deferred store load happens. Any idea how to work around this problem?

    [edit] note that the initialization of the selection also seems to happen in a deferred call, namely Ext.DataView{override}.doSelection is done from a Ext.util.DelayedTask - so my problem here is that there's a race-condition about which one runs first, and for my page I'm working on I happen to lose that race most of the time, which is why it's a problem for me.
    Last edited by geoffrey.mcgill; Sep 28, 2012 at 9:40 PM. Reason: [CLOSED]
  2. #2
    Hi,

    Thanks for the report. We will investigate.

    For now, I can suggest to set initial selection within a Load listener of the Store.
  3. #3
    I did some more investigation and could improve reproduction by increasing the data list of the store:
    protected void Page_Load()
    {
        var list = new object[1000];
        for (int i = 0; i < list.Length; i++)
            list[i] = new object[] { (100 + (i % 100)).ToString() };
        wStore.DataSource = list;
        wStore.DataBind();
    }
    It's not really caused by the larger data store though, in my project site where I originally experienced the issue I usually just have 2-3 elements in the list. I assume increasing size/complexity of the page script shift the timing of the race condition towards the problematic case.

    [edit]
    Setting the selection from a store-load listener is a bit problematic as well, because I just noticed store-load is triggered twice, the first time during the construction of the page before the ListView even exists. Not sure how to detect and 'skip' that first load (not wanting to use a defer call because that was the cause of the problem in the first place, also it causes on/off selection flicker due to multiple initializations).
  4. #4
    After some attempts I am unable to reproduce the initial issue. So, I am not sure how to fix it.

    Any chance for us to get a sample which would reproduce the issue for sure?

    Quote Originally Posted by syncos View Post
    [edit]
    Setting the selection from a store-load listener is a bit problematic as well, because I just noticed store-load is triggered twice, the first time during the construction of the page before the ListView even exists. Not sure how to detect and 'skip' that first load (not wanting to use a defer call because that was the cause of the problem in the first place, also it causes on/off selection flicker due to multiple initializations).
    Setting
    AutoLoad="false"
    and calling
    store.load();
    manually could be a solution to avoid two Load events.
  5. #5
    Alright, I'll try it with manual loading later.

    About reproduction, did you try with the longer data source from my 2nd post? I'm testing with VS 2012 on IE9. The sample is configured (in the project options) to run in IIS express which is installed together with VS 2012 automatically. The original sample shows the issue only upon the first page load, with the longer data source from my second post it also shows on page refreshes (you might want to increase the list length to see if it helps).

    I just tested on current Firefox and it has the same problem with either data source. While it doesn't seem to break on the debugger statement in the selection change listener it still resets the selection a few moments after page load.

    Anyways I'll try to improve the reproduction sample tomorrow.
  6. #6
    Quote Originally Posted by syncos View Post
    About reproduction, did you try with the longer data source from my 2nd post?
    Apologize, I didn't. Now I reproduced. We will investigate!

    Quote Originally Posted by syncos View Post
    Anyways I'll try to improve the reproduction sample tomorrow.
    Please, don't worry. I will be back with an update about the results.
  7. #7
    Thanks for looking into it.
  8. #8
    Quote Originally Posted by Daniil View Post
    Setting
    AutoLoad="false"
    and calling
    store.load();
    manually could be a solution to avoid two Load events.
    That seems to be a working solution. I'm now using AutoLoad=false and wStore.LoadData(list); instead of wStore.DataBind();
  9. #9
    I investigated the problem and can't see a good solution with default AutoLoad="true". Any solution looks like a hack, because the main problem is the fact that the Store is loaded twice. It comes from ExtJS 3 and it is too hard to fix. We will leave it without change in Ext.NET v1.

    So, yes, please use AutoLoad="false". It also gives the benefit in the performance aspect avoiding double requests.

    I would suggest to call the Store load method within a ListView Render method.

    Example
    <%@ Page Language="C#" %>
    
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            var list = new object[1000];
            for (int i = 0; i < list.Length; i++)
            {
                list[i] = new object[] { (100 + (i % 100)).ToString() };
            };
            this.Store1.DataSource = list;
            this.Store1.DataBind();
        }
    </script>
    
    <!DOCTYPE html>
    
    <html>
    <head runat="server">
        <title>Ext.NET Example</title>
    </head>
    <body>
        <ext:ResourceManager runat="server" />
    
        <ext:ListView runat="server" SingleSelect="true" SelectedIndex="0">
            <Store>
                <ext:Store ID="Store1" runat="server" AutoLoad="false">
                    <Reader>
                        <ext:ArrayReader>
                            <Fields>
                                <ext:RecordField Name="Name" />
                            </Fields>
                        </ext:ArrayReader>
                    </Reader>
                </ext:Store>
            </Store>
            <Columns>
                <ext:ListViewColumn DataIndex="Name" />
            </Columns>
            <Listeners>
                <Render Handler="this.store.load();" />
            </Listeners>
        </ext:ListView>
    </body>
    </html>
    However, there is no such issue (double load request) in Ext.NET v2 and SelectedIndex should work well when we will port this functionality to v2.

    Thank you for pointing the problem out!
  10. #10
    Alright, that workaround will do fine. Thanks for the help!

Similar Threads

  1. Replies: 11
    Last Post: Feb 06, 2012, 2:56 PM
  2. Replies: 0
    Last Post: Sep 05, 2011, 2:59 PM
  3. Replies: 4
    Last Post: Mar 19, 2010, 11:35 AM
  4. [CLOSED] Listview with side scroll bar
    By SFritsche in forum 1.x Legacy Premium Help
    Replies: 1
    Last Post: Feb 18, 2010, 5:17 PM
  5. Code behind setting Title property on portlet fails
    By netwearcdz in forum 1.x Help
    Replies: 3
    Last Post: Jan 15, 2010, 3:36 PM

Tags for this Thread

Posting Permissions